SynthesizedAttribute Traversal::evaluateSynthesizedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { SynthesizedAttribute returnAttribute; returnAttribute.node = astNode; SgVarRefExp *varRef = NULL; //set to a var ref child of astNode iff this child is to be //instrumented if (isSgVarRefExp(astNode)) { returnAttribute.isVarRef = true; } else { if (isSgAssignOp(astNode)) { //add other assignment operatrors SynthesizedAttribute leftChild = synthesizedAttributeList[SgBinaryOp_lhs_operand_i]; if (leftChild.isVarRef) { varRef = isSgVarRefExp(leftChild.node); assert(varRef != NULL); instrumentWrite(varRef); } } if (varRef == NULL) { //not else! could be right-hand-side of assignment for (SubTreeSynthesizedAttributes::iterator iter = synthesizedAttributeList.begin(); iter != synthesizedAttributeList.end(); iter++) { if (iter->isVarRef) { varRef = isSgVarRefExp(iter->node); assert (varRef != NULL); instrumentRead(varRef); } } } } return returnAttribute; }
FrontierDetectionForTokenStreamMapping_SynthesizedAttribute FrontierDetectionForTokenStreamMapping::FrontierDetectionForTokenStreamMapping::evaluateSynthesizedAttribute (SgNode* n, FrontierDetectionForTokenStreamMapping_InheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { FrontierDetectionForTokenStreamMapping_SynthesizedAttribute returnAttribute; if (inheritedAttribute.containsFrontier == true) { #if 1 printf ("Marking containsFrontier = true (based on inheritedAttribute) at node = %p = %s \n",n,n->class_name().c_str()); #endif returnAttribute.containsFrontier = inheritedAttribute.containsFrontier; } for (size_t i = 0; i < synthesizedAttributeList.size(); i++) { if (synthesizedAttributeList[i].containsFrontier == true) { #if 1 printf ("Marking containsFrontier = true (based on synthesizedAttribute) at node = %p = %s \n",n,n->class_name().c_str()); #endif returnAttribute.containsFrontier = true; } } // return FrontierDetectionForTokenStreamMapping_SynthesizedAttribute(); return returnAttribute; }
// Functions required by the global tree traversal mechanism ProgramTransformationSynthesizedAttributeType ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, ProgramTransformationInheritedAttributeType inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList) { // Build the synthesizied attribute that this function will return ProgramTransformationSynthesizedAttributeType returnSynthesizedAttribute(astNode); #if 0 printf ("$$$$$ TOP of ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute (astNode = %s) (synthesizedAttributeList.size() = %d) \n", astNode->sage_class_name(),synthesizedAttributeList.size()); // inheritedAttribute.display("In ArrayStatementTraversal::evaluateRewriteInheritedAttribute"); #endif if (astNode->variantT() == V_SgExprStatement) { // The program logic can't reset the returnSynthesizedAttribute for each transformation #if 0 printf ("ERROR: In ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute(): The program logic can't reset the returnSynthesizedAttribute for each transformation... \n"); ROSE_ABORT(); #endif // printf ("Found an expression statement (programTransformation.C) \n"); // We use the operator+=() because more than one transformation function could be called in general. // Below we will call the scalar indexing transformation as a second transformation. Both, and more, // will be called for Expression statements in the future (e.g. indirect addressing). // returnSynthesizedAttribute += arrayAssignmentTransformation(inheritedAttribute,astNode); #if 0 // printf ("Calling arrayAssignmentTransformation() \n"); returnSynthesizedAttribute = arrayAssignmentTransformation(inheritedAttribute,astNode); // arrayAssignmentTransformation(inheritedAttribute,astNode); // printf ("DONE: arrayAssignmentTransformation() \n"); #endif #if 1 // Turn off the scalar indexing transformation for now // returnSynthesizedAttribute += ScalarIndexingArrayStatementTransformation::transformation(project,astNode); // returnSynthesizedAttribute += ScalarIndexingArrayStatementTransformation::transformation(inheritedAttribute,astNode); returnSynthesizedAttribute = arrayScalarIndexingTransformation(inheritedAttribute,astNode); #endif } #if 0 printf ("$$$$$ BOTTOM of attributeAssemblyFunction (astNode = %s) (declaration list size = %d) (returnSynthesizedAttribute.getTransformationSourceCode() = \n%s) \n", astNode->sage_class_name(), returnSynthesizedAttribute.variableDeclarationList.size(), returnSynthesizedAttribute.getSourceCodeString().c_str()); #endif return returnSynthesizedAttribute; }
DOTSynthesizedAttribute AstDOTGeneration::evaluateSynthesizedAttribute(SgNode* node, DOTInheritedAttribute ia, SubTreeSynthesizedAttributes l) { SubTreeSynthesizedAttributes::iterator iter; ROSE_ASSERT(node); // printf ("AstDOTGeneration::evaluateSynthesizedAttribute(): node = %s \n",node->class_name().c_str()); // DQ (5/3/2006): Skip this IR node if it is specified as such in the inherited attribute if (ia.skipSubTree == true) { // I am unclear if I should return NULL or node as a parameter to DOTSynthesizedAttribute // Figured this out: if we return a valid pointer then we get a node in the DOT graph // (with just the pointer value as a label), where as if we return a DOTSynthesizedAttribute // with a NUL pointer then the node will NOT appear in the DOT graph. // return DOTSynthesizedAttribute(node); return DOTSynthesizedAttribute(NULL); } string nodeoption; if(AstTests::isProblematic(node)) { // cout << "problematic node found." << endl; nodeoption="color=\"orange\" "; } string nodelabel=string("\\n")+node->class_name(); // DQ (1/24/2009): Added support for output of isForward flag in the dot graph. SgDeclarationStatement* genericDeclaration = isSgDeclarationStatement(node); if (genericDeclaration != NULL) { // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. string name = (genericDeclaration->isForward() == true) ? "isForward" : "!isForward"; ROSE_ASSERT(name.empty() == false); // DQ (3/20/2011): Added class names to the generated dot file graphs of the AST. SgClassDeclaration* classDeclaration = isSgClassDeclaration(genericDeclaration); if (classDeclaration != NULL) { nodelabel += string("\\n") + classDeclaration->get_name(); } // DQ (3/20/2011): Added function names to the generated dot file graphs of the AST. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(genericDeclaration); if (functionDeclaration != NULL) { nodelabel += string("\\n") + functionDeclaration->get_name(); } nodelabel += string("\\n") + name; } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgInitializedName* initializedName = isSgInitializedName(node); if (initializedName != NULL) { nodelabel += string("\\n") + initializedName->get_name(); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgIntVal* intValue = isSgIntVal(node); if (intValue != NULL) { nodelabel += string("\\n value = ") + StringUtility::numberToString(intValue->get_value()); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgVarRefExp* varRefExp = isSgVarRefExp(node); if (varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); string name = variableSymbol->get_name(); nodelabel += string("\\n name = ") + name; } // DQ (1/19/2009): Added support for output of what specific instrcution this is in the dot graph. SgAsmInstruction* genericInstruction = isSgAsmInstruction(node); if (genericInstruction != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. #if 1 string unparsedInstruction = unparseInstruction(genericInstruction); string addressString = StringUtility::numberToString( (void*) genericInstruction->get_address() ); // string name = genericInstruction->get_mnemonic(); string name = unparsedInstruction + "\\n address: " + addressString; #else string name = unparsedInstruction + "\\n" + addressString; #endif ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } SgAsmExpression* genericExpression = isSgAsmExpression(node); if (genericExpression != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT string name = unparseExpression(genericExpression, NULL, NULL); ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (10/29/2008): Added some support for additional output of internal names for specific IR nodes. // In generall there are long list of these IR nodes in the binary and this helps make some sense of // the lists (sections, symbols, etc.). SgAsmExecutableFileFormat* binaryFileFormatNode = isSgAsmExecutableFileFormat(node); if (binaryFileFormatNode != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // The case of binary file format IR nodes can be especially confusing so we want the // default to output some more specific information for some IR nodes (e.g. sections). string name; SgAsmGenericSection* genericSection = isSgAsmGenericSection(node); if (genericSection != NULL) { SgAsmGenericString* genericString = genericSection->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmGenericSymbol* genericSymbol = isSgAsmGenericSymbol(node); if (genericSymbol != NULL) { SgAsmGenericString* genericString = genericSymbol->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); if (name.empty() == true) name = "no_name_for_symbol"; } SgAsmGenericDLL* genericDLL = isSgAsmGenericDLL(node); if (genericDLL != NULL) { SgAsmGenericString* genericString = genericDLL->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmPEImportItem* peImportItem = isSgAsmPEImportItem(node); if (peImportItem != NULL) { SgAsmGenericString* genericString = peImportItem->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmDwarfLine* asmDwarfLine = isSgAsmDwarfLine(node); if (asmDwarfLine != NULL) { char buffer[100]; // It does not work to embed the "\n" into the single sprintf parameter. // sprintf(buffer," Addr: 0x%08"PRIx64" \n line: %d col: %d ",asmDwarfLine->get_address(),asmDwarfLine->get_line(),asmDwarfLine->get_column()); sprintf(buffer,"Addr: 0x%08"PRIx64,asmDwarfLine->get_address()); name = buffer; sprintf(buffer,"line: %d col: %d",asmDwarfLine->get_line(),asmDwarfLine->get_column()); name += string("\\n") + buffer; } SgAsmDwarfConstruct* asmDwarfConstruct = isSgAsmDwarfConstruct(node); if (asmDwarfConstruct != NULL) { name = asmDwarfConstruct->get_name(); } #if 0 // This might not be the best way to implement this, since we want to detect common base classes of IR nodes. switch (node->variantT()) { case V_SgAsmElfSection: { SgAsmElfSection* n = isSgAsmElfSection(node); name = n->get_name(); break; } default: { // No additional information is suggested for the default case! } } #endif if (name.empty() == false) nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (11/29/2008): Output the directives in the label of the IR node. SgC_PreprocessorDirectiveStatement* preprocessorDirective = isSgC_PreprocessorDirectiveStatement(node); if (preprocessorDirective != NULL) { string s = preprocessorDirective->get_directiveString(); // Change any double quotes to single quotes so that DOT will not misunderstand the generated lables. while (s.find("\"") != string::npos) { s.replace(s.find("\""),1,"\'"); } if (s.empty() == false) nodelabel += string("\\n") + s; } nodelabel += additionalNodeInfo(node); // DQ (11/1/2003) added mechanism to add additional options (to add color, etc.) // nodeoption += additionalNodeOptions(node); string additionalOptions = additionalNodeOptions(node); // printf ("nodeoption = %s size() = %ld \n",nodeoption.c_str(),nodeoption.size()); // printf ("additionalOptions = %s size() = %ld \n",additionalOptions.c_str(),additionalOptions.size()); string x; string y; x += additionalOptions; nodeoption += additionalOptions; DOTSynthesizedAttribute d(0); // DQ (7/27/2008): Added mechanism to support pruning of AST bool commentoutNode = commentOutNodeInGraph(node); if (commentoutNode == true) { // DQ (11/10/2008): Fixed to only output message when (verbose_level > 0); command-line option. // DQ (7/27/2008): For now just return to test this mechanism, then we want to add comment "//" propoerly to generated DOT file. if (SgProject::get_verbose() > 0) { printf ("Skipping the use of this IR node in the DOT Graph \n"); } } else { // ************************** switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(ia.tdbuTracePos,tdbuTrace)+nodelabel,nodeoption); break; case PREORDER: case TOPDOWN: dotrep.addNode(node,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); break; case POSTORDER: case BOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(buTrace)+nodelabel,nodeoption); break; default: assert(false); } ++tdbuTrace; ++buTrace; // add edges or null values int testnum=0; for (iter = l.begin(); iter != l.end(); iter++) { string edgelabel = string(node->get_traversalSuccessorNamesContainer()[testnum]); string toErasePrefix = "p_"; if (AstTests::isPrefix(toErasePrefix,edgelabel)) { edgelabel.erase(0, toErasePrefix.size()); } if ( iter->node == NULL) { // SgNode* snode=node->get_traversalSuccessorContainer()[testnum]; AstSuccessorsSelectors::SuccessorsContainer c; AstSuccessorsSelectors::selectDefaultSuccessors(node,c); SgNode* snode=c[testnum]; // isDefault shows that the default constructor for synth attribute was used if (l[testnum].isDefault() && snode && (visitedNodes.find(snode) != visitedNodes.end()) ) { // handle bugs in SAGE dotrep.addEdge(node,edgelabel,snode,"dir=forward arrowhead=\"odot\" color=red "); } else { if (snode == NULL) { dotrep.addNullValue(node,"",edgelabel,""); } } } else { // DQ (3/5/2007) added mechanism to add additional options (to add color, etc.) string edgeoption = additionalEdgeOptions(node,iter->node,edgelabel); switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=both"); break; case PREORDER: case TOPDOWN: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=forward"); break; case POSTORDER: case BOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=back"); break; default: assert(false); } } testnum++; } // ************************** } // DQ (7/4/2008): Support for edges specified in AST attributes AstAttributeMechanism* astAttributeContainer = node->get_attributeMechanism(); if (astAttributeContainer != NULL) { // Loop over all the attributes at this IR node for (AstAttributeMechanism::iterator i = astAttributeContainer->begin(); i != astAttributeContainer->end(); i++) { // std::string name = i->first; AstAttribute* attribute = i->second; ROSE_ASSERT(attribute != NULL); // This can return a non-empty list in user-defined attributes (derived from AstAttribute). // printf ("Calling attribute->additionalNodeInfo() \n"); std::vector<AstAttribute::AttributeNodeInfo> nodeList = attribute->additionalNodeInfo(); // printf ("nodeList.size() = %lu \n",nodeList.size()); for (std::vector<AstAttribute::AttributeNodeInfo>::iterator i_node = nodeList.begin(); i_node != nodeList.end(); i_node++) { SgNode* nodePtr = i_node->nodePtr; string nodelabel = i_node->label; string nodeoption = i_node->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding a node nodelabel = %s nodeoption = %s \n",nodelabel.c_str(),nodeoption.c_str()); // dotrep.addNode(NULL,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); dotrep.addNode( nodePtr, dotrep.traceFormat(ia.tdTracePos) + nodelabel, nodeoption ); } // printf ("Calling attribute->additionalEdgeInfo() \n"); std::vector<AstAttribute::AttributeEdgeInfo> edgeList = attribute->additionalEdgeInfo(); // printf ("edgeList.size() = %lu \n",edgeList.size()); for (std::vector<AstAttribute::AttributeEdgeInfo>::iterator i_edge = edgeList.begin(); i_edge != edgeList.end(); i_edge++) { string edgelabel = i_edge->label; string edgeoption = i_edge->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding an edge from i_edge->fromNode = %p to i_edge->toNode = %p edgelabel = %s edgeoption = %s \n",i_edge->fromNode,i_edge->toNode,edgelabel.c_str(),edgeoption.c_str()); dotrep.addEdge(i_edge->fromNode,edgelabel,i_edge->toNode,edgeoption + "dir=forward"); } } } switch(node->variantT()) { // DQ (9/1/2008): Added case for output of SgProject rooted DOT file. // This allows source code and binary files to be combined into the same DOT file. case V_SgProject: { SgProject* project = dynamic_cast<SgProject*>(node); ROSE_ASSERT(project != NULL); string generatedProjectName = SageInterface::generateProjectName( project ); // printf ("generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); if (generatedProjectName.length() > 40) { // printf ("Warning: generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); generatedProjectName = "aggregatedFileNameTooLong"; printf ("Proposed (generated) filename is too long, shortened to: %s \n",generatedProjectName.c_str()); } string filename = string("./") + generatedProjectName + ".dot"; // printf ("generated filename for dot file (from SgProject) = %s \n",filename.c_str()); if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgProject IR node (filename = %s) \n",filename.c_str()); dotrep.writeToFileAsGraph(filename); break; } // case V_SgFile: case V_SgSourceFile: case V_SgBinaryComposite: { SgFile* file = dynamic_cast<SgFile*>(node); ROSE_ASSERT(file != NULL); string original_filename = file->getFileName(); // DQ (7/4/2008): Fix filenamePostfix to go before the "." // string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + "."+filenamePostfix+"dot"; string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + filenamePostfix + ".dot"; // printf ("generated filename for dot file (from SgSourceFile or SgBinaryComposite) = %s file->get_parent() = %p \n",filename.c_str(),file->get_parent()); // printf ("file->get_parent() = %p \n",file->get_parent()); // cout << "generating DOT file (from SgSourceFile or SgBinaryComposite): " << filename2 << " ... "; // DQ (9/1/2008): this effects the output of DOT files when multiple files are specified // on the command line. A SgProject is still built even when a single file is specificed // on the command line, however there are cases where a SgFile can be built without a // SgProject and this case allows those SgFile rooted subtrees to be output as DOT files. // If there is a SgProject then output the dot file from there, else output as a SgFile. if (file->get_parent() == NULL) { // If there is no SgProject then output the file now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (no SgProject available) \n"); dotrep.writeToFileAsGraph(filename); } else { // There is a SgProject IR node, but if we will be traversing it we want to output the // graph then (so that the graph will include the SgProject IR nodes and connect multiple // files (SgSourceFile or SgBinaryComposite IR nodes). if ( visitedNodes.find(file->get_parent()) == visitedNodes.end() ) { // This SgProject node was not input as part of the traversal, // so we will not be traversing the SgProject IR nodes and we // have to output the graph now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (SgProject was not traversed) \n"); dotrep.writeToFileAsGraph(filename); } else { if ( SgProject::get_verbose() >= 1 ) printf ("Skip the output of the DOT graph from the SgFile IR node (SgProject will be traversed) \n"); } } // cout << "done." << endl; break; } // DQ (7/23/2005): Implemented default case to avoid g++ warnings // about enum values not handled by this switch default: { // nothing to do here break; } } d.node = node; return d; }
SynthesizedAttribute CreateCloneDetectionVectors::evaluateSynthesizedAttribute ( SgNode* astNode, SubTreeSynthesizedAttributes synthesizedAttributeList ) { static int currentStride = 0; SynthesizedAttribute returnAttribute; //test.push_back(astNode->class_name()); //initialize to zero for( int i = 0; i < V_SgNumVariants; ++i) { (returnAttribute.nodesInSubtree)[i] = 0; } nodeToCloneVector[astNode] = returnAttribute.nodesInSubtree; //Add current node to vector (returnAttribute.nodesInSubtree)[astNode->variantT()]+=1; //Add the vectors in the subtrees of the vector to this vector for(SubTreeSynthesizedAttributes::iterator iItr = synthesizedAttributeList.begin(); iItr != synthesizedAttributeList.end(); ++iItr){ #if 0 for( int i = 0; i < lengthVariantT; i++) { std::cout << (iItr->nodesInSubtree)[i] << " " ; } std::cout << std::endl << std::endl; #endif returnAttribute.addToVector ( (*iItr).nodesInSubtree ); } //std::cout << "\n\nVector of names" << std::endl; #if 0 //Print out the number of elements found for each variant in the subtree for(int i = 0; i < lengthVariantT; i++ ){ if(returnAttribute.nodesInSubtree[i] > 0) std::cout << returnAttribute.nodesInSubtree[i] << " " << variantToName[i] << " "; } std::cout << "\n\n"; #endif //Write to the file specified in the config file on the commandline if(std::find(variantToWriteToFile.begin(), variantToWriteToFile.end(), astNode->variantT()) != variantToWriteToFile.end()) { int numTokens = 0; for(unsigned int i=0; i < variantNumVec.size(); i++ ) { numTokens+= returnAttribute.nodesInSubtree[i]; } if( numTokens >= minTokens ) { currentStride++; //To implement the concept of a stride we need to not overcount //subtrees. But I am not sure if the vectors which contains this vector //should have a smaller for(unsigned int i = 0; i < variantNumVec.size(); i++ ){ mergedVector[i]+= returnAttribute.nodesInSubtree[i]; } if( currentStride >= stride ){ VariantVector stmts(V_SgStatement); VariantVector exprs(V_SgExpression); VariantVector decls(V_SgDeclarationStatement); int n_stmts = 0; int n_exprs = 0; int n_decls = 0; for( VariantVector::iterator iItr = stmts.begin(); iItr != stmts.end(); ++iItr ) n_stmts+=stmts[*iItr]; for( VariantVector::iterator iItr = exprs.begin(); iItr != exprs.end(); ++iItr ) n_exprs+=exprs[*iItr]; for( VariantVector::iterator iItr = decls.begin(); iItr != decls.end(); ++iItr ) n_decls+=decls[*iItr]; myfile << "# FILE:" <<astNode->get_file_info()->get_filenameString(); myfile << ", LINE:" <<astNode->get_file_info()->get_line(); myfile << ", OFFSET:" <<astNode->get_file_info()->get_col(); myfile << ", NODE_KIND:" << astNode->variantT(); myfile << ", CONTEXT_KIND:0, NEIGHBOR_KIND:0"; myfile << ", NUM_NODE:" << numTokens; myfile << ", NUM_DECL:" << n_decls; myfile << ", NUM_STMT:" << n_stmts; myfile << ", NUM_EXPR:" << n_exprs; myfile << ", TBID:0, TEID:0, VARs:{}0,"; myfile << std::endl; for(unsigned int i = 0; i < variantNumVec.size(); i++ ){ myfile << mergedVector[i] << " "; //std::cout << returnAttribute.nodesInSubtree[variantNumVec[i]] << " " << roseGlobalVariantNameList[variantNumVec[i]] << " "; } myfile << std::endl; currentStride = 0; for(unsigned int i = 0; i < variantNumVec.size(); i++ ){ mergedVector[i] = 0; } } } } return returnAttribute; }
adRecord evaluateSynthesizedAttribute (SgNode* n, aiRecord inherited, SubTreeSynthesizedAttributes synthesized ) { //printf("evaluateSynthesizedAttribute(n=%p)\n"); adRecord dr(n); SgPntrArrRefExp* arrRef; if((arrRef = isSgPntrArrRefExp(n))) { //printf("evaluateSynthesizedAttribute() arrRef->lhs=%p, arrRef->rhs=%p\n", arrRef->get_lhs_operand(), ); bool found=false; // look through both the synthesized attributes // (one from the SgPntrArrRefExp's array name subtree and one from the index subtree) // get the name subtree for(SubTreeSynthesizedAttributes::iterator it=synthesized.begin(); it!=synthesized.end(); it++) { // if this synthesized attribute comes from SgPntrArrRefExp's array name subtree // (there should be only one such subtree) if((*it).origin == arrRef->get_lhs_operand()) { // copy over the info from the name subtree found = true; dr.arrayDim=(*it).arrayDim+1; // if the array name expression hasn't been found yet, this // SgPntrArrRefExp's array name subtree must be it if((*it).arrayNameExp==NULL) dr.arrayNameExp = arrRef->get_lhs_operand(); // otherwise, the real array name expression is deeper in the array name subtree, so just copy it over else dr.arrayNameExp = (*it).arrayNameExp; // initialize this SgPntrArrRefExp's list of indexes from the lower-level list dr.indexExprs = (*it).indexExprs; // break; } } ROSE_ASSERT(found); found = false; // get the index subtree for(SubTreeSynthesizedAttributes::iterator it=synthesized.begin(); it!=synthesized.end(); it++) { // if this synthesized attribute comes from SgPntrArrRefExp's index subtree // (there should be only one such subtree) if((*it).origin == arrRef->get_rhs_operand()) { found = true; // add the current index expression to this SgPntrArrRefExp's list of indexes dr.indexExprs.push_front(isSgExpression((*it).origin)); } } ROSE_ASSERT(found); } /* if(isSgPntrArrRefExp(n)) printf("SgPntrArrRefExp:0x%x UP arrayIndexFlag=%d arrayNameExp=0x%x arrayDim=%d\n", n, dr.arrayIndexFlag, dr.arrayNameExp, dr.arrayDim); else printf("SgNode:0x%x UP arrayIndexFlag=%d arrayNameExp=0x%x arrayDim=%d\n", n, dr.arrayIndexFlag, dr.arrayNameExp, dr.arrayDim); printf(" <%s>\n", n->unparseToString().c_str());*/ // label this node with its read/write access information arrIndexAttribute* aiAttr = new arrIndexAttribute(dr); char attrName[100]; sprintf(attrName, "ArrayIndex: [%d, %d, %p, %d]", dr.arrayIndexFlag, dr.topArrayRefExpFlag, dr.arrayNameExp, dr.arrayDim); n->addNewAttribute(attrName, aiAttr); n->updateAttribute("ArrayIndex", aiAttr); return dr; }
StencilEvaluation_SynthesizedAttribute StencilEvaluationTraversal::evaluateSynthesizedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { StencilEvaluation_SynthesizedAttribute return_synthesizedAttribute; #if 0 printf ("In StencilEvaluationTraversal::evaluateSynthesizedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundStencilOffsetFSM = false; SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL && inheritedAttribute.stencilOffsetFSM != NULL) { #if 0 printf ("Found pair<Shift,double>(x,y): set then in the synthesizedAttribute: astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif return_synthesizedAttribute.stencilOffsetFSM = inheritedAttribute.stencilOffsetFSM; return_synthesizedAttribute.stencilCoeficientValue = inheritedAttribute.stencilCoeficientValue; #if 0 printf ("return_synthesizedAttribute.stencilCoeficientValue = %f \n",return_synthesizedAttribute.stencilCoeficientValue); #endif foundStencilOffsetFSM = true; } // There should only be a single child set with a pair<Shift,double>(x,y) object. for (size_t i = 0; i < synthesizedAttributeList.size(); i++) { if (synthesizedAttributeList[i].stencilOffsetFSM != NULL) { // Check that the return_synthesizedAttribute.stencilOffsetFSM has not already been set. // This could happend if we allows nesting of pair<Shift,double>(x,y) within itself (not allowed). #if 0 printf ("synthesizedAttributeList[i].stencilOffsetFSM != NULL \n"); #endif // ROSE_ASSERT(foundStencilOffsetFSM == false); if (foundStencilOffsetFSM == false) { #if 0 printf ("foundStencilOffsetFSM == false \n"); #endif // ROSE_ASSERT(return_synthesizedAttribute.stencilOffsetFSM == NULL); if (return_synthesizedAttribute.stencilOffsetFSM == NULL) { #if 0 printf ("return_synthesizedAttribute.stencilOffsetFSM != NULL \n"); #endif return_synthesizedAttribute.stencilOffsetFSM = synthesizedAttributeList[i].stencilOffsetFSM; return_synthesizedAttribute.stencilCoeficientValue = synthesizedAttributeList[i].stencilCoeficientValue; } foundStencilOffsetFSM = true; } } } // This allows us to find the variables of type vector<Point> and vector<double> used as an alternative way // to specify a stencil (using the Stencil constructor that takes these variables as input arguments). // It relies upon a previous traversal to have identified the inputs to Stencil constructor. // This support is incomplete while I focus on the alternative approach to the specification of the stencil // using intremental union of a stencil with a pair<Shift,double>() template instantiation. SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(astNode); if (variableDeclaration != NULL) { // Get the SgInitializedName from the SgVariableDeclaration. SgInitializedName* initializedName = SageInterface::getFirstInitializedName(variableDeclaration); #if 0 printf ("In evaluateInheritedAttribute(): case SgInitializedName from variable declaration: initializedName = %p name = %s \n",initializedName,initializedName->get_name().str()); #endif bool foundStencilDeclaration = false; if (find(stencilInputInitializedNameList.begin(),stencilInputInitializedNameList.end(),initializedName) != stencilInputInitializedNameList.end()) { #if 0 printf ("Found declaration associated with stencil input: initializedName = %p = %s name = %s \n",initializedName,initializedName->class_name().c_str(),initializedName->get_name().str()); #endif // Build the finite state machine for the stencil and add it to the map using the name (in SgInitializedName) as a key. // For now we assume that the stencil specification is using the default construction. if (initializedName->get_initptr() != NULL) { printf ("FIXME: This declaration of a stencil appears to have constrcutor arguments (this not the default constuctor as interprest below). \n"); #if 0 ROSE_ASSERT(false); #endif } foundStencilDeclaration = true; } else { // Verify that this is a Stencil declaration. SgClassType* classType = isSgClassType(initializedName->get_type()); if (classType != NULL) { // Check if this is associated with a template instantiation. SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classType->get_declaration()); if (templateInstantiationDecl != NULL) { #if 0 printf ("case SgTemplateInstaiationDecl: class name = %s \n",classType->get_name().str()); printf ("case SgTemplateInstaiationDecl: templateInstantiationDecl->get_templateName() = %s \n",templateInstantiationDecl->get_templateName().str()); #endif if (templateInstantiationDecl->get_templateName() == "Stencil") { #if 0 printf ("This is verified to be associated with the Stencil template class \n"); #endif foundStencilDeclaration = true; } } } } if (foundStencilDeclaration == true) { string name = initializedName->get_name(); ROSE_ASSERT(stencilMap.find(name) == stencilMap.end()); // stencilMap[name] = new StencilFSM(); StencilFSM* stencilFSM = new StencilFSM(); ROSE_ASSERT(stencilFSM != NULL); stencilMap[name] = stencilFSM; ROSE_ASSERT(stencilMap.find(name) != stencilMap.end()); #if 0 printf ("Added StencilFSM to stencilMap using name = %s \n",name.c_str()); #endif #if 0 printf ("Trigger an event on the stencilFSM ========================== %p \n",stencilFSM); printf (" --- Use the return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif if (return_synthesizedAttribute.stencilOffsetFSM != NULL) { // Trigger the event to add the stencil offset to the stencil. // Trigger the event on the finite state machine using the elements saved in the synthesized attribute. StencilFSM stencil_rhs (*(return_synthesizedAttribute.stencilOffsetFSM),return_synthesizedAttribute.stencilCoeficientValue); // This reproduces the same semantics in our finite state machine as the Stencil class's operator+() // in the stencil specification. but this permits use to accumulate the state at compile time. stencilFSM->operator+(stencil_rhs); // We have now used these values so avoid letting then be used again. return_synthesizedAttribute.stencilOffsetFSM = NULL; return_synthesizedAttribute.stencilCoeficientValue = 0.0; } #if 0 stencilFSM->display("after FSM stencil default construction plus union event: StencilEvaluationTraversal::evaluateSynthesizedAttribute()"); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } } // Recognize member function calls on "Stencil" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = true; bool isTemplateFunctionInstantiation = true; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Stencil",isTemplateClass,"operator+",isTemplateFunctionInstantiation); if (return_synthesizedAttribute.stencilOffsetFSM != NULL && functionCallExp != NULL) { // This is the DSL specific part of the synthesized attribute evaluation. ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); #if 0 printf ("This is verified to be the operator+ member function of the Stencil templated class (so this corresponds to an event in the Stencil finite state machine) \n"); printf (" --- stencil object name = %s \n",name.c_str()); #endif // Lookup the stencil FSM in the map of stencil FSMs using the name as the key. ROSE_ASSERT(stencilMap.find(name) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[name]; ROSE_ASSERT(stencilFSM != NULL); #if 0 printf ("Trigger an event on the stencilFSM ========================== %p \n",stencilFSM); printf (" --- Use the return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif // Make sure we have the input parameter for the stencil's finite state machine. ROSE_ASSERT(return_synthesizedAttribute.stencilOffsetFSM != NULL); // Trigger the event on the finite state machine using the elements saved in the synthesized attribute. StencilFSM stencil_rhs (*(return_synthesizedAttribute.stencilOffsetFSM),return_synthesizedAttribute.stencilCoeficientValue); // This reproduces the same semantics in our finite state machine as the Stencil class's operator+() // in the stencil specification. but this permits use to accumulate the state at compile time. stencilFSM->operator+(stencil_rhs); // We have now used these values so avoid letting then be used again. return_synthesizedAttribute.stencilOffsetFSM = NULL; return_synthesizedAttribute.stencilCoeficientValue = 0.0; #if 0 stencilFSM->display("after FSM stencil union event: StencilEvaluationTraversal::evaluateSynthesizedAttribute()"); #endif } #if 0 printf ("Leaving StencilEvaluationTraversal::evaluateSynthesizedAttribute(): return_synthesizedAttribute.stencilOffsetFSM = %p \n",return_synthesizedAttribute.stencilOffsetFSM); #endif #if 0 printf ("Leaving StencilEvaluationTraversal::evaluateSynthesizedAttribute(): return_synthesizedAttribute.stencilCoeficientValue = %f \n",return_synthesizedAttribute.stencilCoeficientValue); #endif return return_synthesizedAttribute; }
// void RemoveConstantFoldedValue::visit ( SgNode* node ) RemoveConstantFoldedValueSynthesizedAttribute RemoveConstantFoldedValue::evaluateSynthesizedAttribute ( SgNode* node, SubTreeSynthesizedAttributes synthesizedAttributeList ) { ROSE_ASSERT(node != NULL); // DQ (3/11/2006): Set NULL pointers where we would like to have none. #if 0 #if 0 // Avoid excessive output. if (isSgFunctionDeclaration(node) == NULL && isSgInitializedName(node) == NULL && isSgFunctionParameterList(node) == NULL) printf ("In RemoveConstantFoldedValue::evaluateSynthesizedAttribute(): node = %p = %s synthesizedAttributeList.size() = %" PRIuPTR " \n",node,node->class_name().c_str(),synthesizedAttributeList.size()); #else printf ("In RemoveConstantFoldedValue::evaluateSynthesizedAttribute(): node = %p = %s synthesizedAttributeList.size() = %" PRIuPTR " \n",node,node->class_name().c_str(),synthesizedAttributeList.size()); #endif #endif // Here we reset the pointer to the constant folded value to be the pointer to the original expression tree. SubTreeSynthesizedAttributes::iterator i = synthesizedAttributeList.begin(); while (i != synthesizedAttributeList.end()) { #if 0 // Avoid excessive output. if (isSgFunctionDeclaration(i->node) == NULL && isSgInitializedName(i->node) == NULL && isSgFunctionParameterList(i->node) == NULL && i->node != NULL) printf ("synthesizedAttribute = %p = %s \n",i->node,(i->node != NULL) ? i->node->class_name().c_str() : "NULL"); #endif // DQ (10/8/2011): Refectored this code so that we could better support chains of original expression trees (see test2011_146.C). handleTheSynthesizedAttribute(node,*i); i++; } // Here we force the nested traversal of the originalExpressionTree, since it is not traversed as part of the AST. // Note that these are not always leaf nodes that we want to interogate (see test2011_140.C). // DQ (9/24/2011): I think this is the wrong place to process this case (see test2011_140.C). // DQ (9/24/2011): We have fixed the AST traversal to no longer traverse originalExpressionTree subtree's (since // it make analysis using the traversal redundant with the constant folded values). // If the current node is an expression and a leaf node of the AST, then check if it has an originalExpressionTree, // since we no longer traverse the originalExpressionTree as part of the definition of the AST. // SgExpression* leafExpression = (synthesizedAttributeList.empty() == true) ? isSgExpression(node) : NULL; SgExpression* expression = isSgExpression(node); if (expression != NULL) { #if 0 printf ("In RemoveConstantFoldedValue::evaluateSynthesizedAttribute(): Found an expression \n"); #endif SgExpression* originalExpressionTree = expression->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Found an expression with a valid originalExpressionTree\n"); #endif // Make sure that the traversal will see the nested subtrees of any originalExpressionTree (since they may have constant folded subexpresions). RemoveConstantFoldedValue nestedOriginalExpressionTreeTraversal; RemoveConstantFoldedValueSynthesizedAttribute nestedSynthesizedAttribute = nestedOriginalExpressionTreeTraversal.traverse(originalExpressionTree); #if 0 // DQ (10/8/2011): We should not handl this here, I think. handleTheSynthesizedAttribute(node,nestedSynthesizedAttribute); #endif #if 0 printf ("DONE: Found an expression with a valid originalExpressionTree nestedSynthesizedAttribute \n"); #endif } } return RemoveConstantFoldedValueSynthesizedAttribute(node); }
// first visits the VarRef and then creates entry in operandDatabase which is // useful in expressionStatement transformation. Thus, we replace the VarRef // at the end of the traversal and insert loops during traversal ArrayAssignmentStatementQuerySynthesizedAttributeType ArrayAssignmentStatementTransformation::evaluateSynthesizedAttribute( SgNode* astNode, ArrayAssignmentStatementQueryInheritedAttributeType arrayAssignmentStatementQueryInheritedData, SubTreeSynthesizedAttributes synthesizedAttributeList) { // This function assembles the elements of the input list (a list of char*) to form the output (a single char*) #if DEBUG printf ("\n$$$$$ TOP of evaluateSynthesizedAttribute (astNode = %s) (synthesizedAttributeList.size() = %d) \n", astNode->sage_class_name(),synthesizedAttributeList.size()); //cout << " Ast node string: " << astNode->unparseToString() << endl; #endif // Build the return value for this function ArrayAssignmentStatementQuerySynthesizedAttributeType returnSynthesizedAttribute(astNode); // Iterator used within several error checking loops (not sure we should declare it here!) vector<ArrayAssignmentStatementQuerySynthesizedAttributeType>::iterator i; // Make a reference to the global operand database OperandDataBaseType & operandDataBase = accumulatorValue.operandDataBase; // Make sure the data base has been setup properly ROSE_ASSERT(operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess); ROSE_ASSERT(operandDataBase.dimension > -1); // Build up a return string string returnString = ""; string operatorString; // Need to handle all unary and binary operators and variables (but not much else) switch (astNode->variant()) { case FUNC_CALL: { // Error checking: Verify that we have a SgFunctionCallExp object SgFunctionCallExp* functionCallExpression = isSgFunctionCallExp(astNode); ROSE_ASSERT(functionCallExpression != NULL); string operatorName = TransformationSupport::getFunctionName(functionCallExpression); ROSE_ASSERT(operatorName.c_str() != NULL); string functionTypeName = TransformationSupport::getFunctionTypeName(functionCallExpression); if ((functionTypeName != "doubleArray") && (functionTypeName != "floatArray") && (functionTypeName != "intArray")) { // Use this query to handle only A++ function call expressions // printf ("Break out of overloaded operator processing since type = %s is not to be processed \n",functionTypeName.c_str()); break; } else { // printf ("Processing overloaded operator of type = %s \n",functionTypeName.c_str()); } ROSE_ASSERT((functionTypeName == "doubleArray") || (functionTypeName == "floatArray") || (functionTypeName == "intArray")); // printf ("CASE FUNC_CALL: Overloaded operator = %s \n",operatorName.c_str()); // Get the number of parameters to this function SgExprListExp* exprListExp = functionCallExpression->get_args(); ROSE_ASSERT(exprListExp != NULL); SgExpressionPtrList & expressionPtrList = exprListExp->get_expressions(); int numberOfParameters = expressionPtrList.size(); TransformationSupport::operatorCodeType operatorCodeVariant = TransformationSupport::classifyOverloadedOperator(operatorName.c_str(), numberOfParameters); // printf ("CASE FUNC_CALL: numberOfParameters = %d operatorCodeVariant = %d \n", // numberOfParameters,operatorCodeVariant); ROSE_ASSERT(operatorName.length() > 0); // Separating this case into additional cases makes up to some // extent for using a more specific higher level grammar. switch (operatorCodeVariant) { case TransformationSupport::ASSIGN_OPERATOR_CODE: { vector<ArrayOperandDataBase>::iterator lhs = operandDataBase.arrayOperandList.begin(); vector<ArrayOperandDataBase>::iterator rhs = lhs; rhs++; while (rhs != operandDataBase.arrayOperandList.end()) { // look at the operands on the rhs for a match with the one on the lhs if ((*lhs).arrayVariableName == (*rhs).arrayVariableName) { // A loop dependence has been identified // Mark the synthesized attribute to record // the loop dependence within this statement returnSynthesizedAttribute.setLoopDependence(TRUE); } rhs++; } break; } default: break; } break; } case EXPR_STMT: { printf("Found a EXPR STMT expression %s\n", astNode->unparseToString().c_str()); // The assembly associated with the SgExprStatement is what // triggers the generation of the transformation string SgExprStatement* expressionStatement = isSgExprStatement(astNode); ROSE_ASSERT(expressionStatement != NULL); ArrayAssignmentStatementQuerySynthesizedAttributeType innerLoopTransformation = synthesizedAttributeList[SgExprStatement_expression]; // Call another global support // Create appropriate macros, nested loops, etc expressionStatementTransformation(expressionStatement, arrayAssignmentStatementQueryInheritedData, innerLoopTransformation, operandDataBase); break; } // case TransformationSupport::PARENTHESIS_OPERATOR_CODE: { // ROSE_ASSERT (operatorName == "operator()"); // // printf ("Indexing of InternalIndex objects in not implemented yet! \n"); // // // Now get the operands out and search for the offsets in the index objects // // // We only want to pass on the transformationOptions as inherited attributes // // to the indexOffsetQuery // // list<int> & transformationOptionList = arrayAssignmentStatementQueryInheritedData.getTransformationOptions(); // // // string offsetString; // string indexOffsetString[6]; // = {NULL,NULL,NULL,NULL,NULL,NULL}; // // // retrieve the variable name from the data base (so that we can add the associated index object names) // // printf ("WARNING (WHICH OPERAND TO SELECT): operandDataBase.size() = %d \n",operandDataBase.size()); // // ROSE_ASSERT (operandDataBase.size() == 1); // // string arrayVariableName = returnSynthesizedAttribute.arrayOperandList[0].arrayVariableName; // int lastOperandInDataBase = operandDataBase.size() - 1; // ArrayOperandDataBase & arrayOperandDB = operandDataBase.arrayOperandList[lastOperandInDataBase]; // // string arrayVariableName = // // operandDataBase.arrayOperandList[operandDataBase.size()-1].arrayVariableName; // string arrayVariableName = arrayOperandDB.arrayVariableName; // // string arrayDataPointerNameSubstring = string("_") + arrayVariableName; // // // printf ("***** WARNING: Need to get identifier from the database using the ArrayOperandDataBase::generateIdentifierString() function \n"); // // if (expressionPtrList.size() == 0) { // // Case of A() (index object with no offset integer expression) Nothing to do here (I think???) // printf("Special case of Indexing with no offset! exiting ... \n"); // ROSE_ABORT(); // // returnString = ""; // } else { // // Get the value of the offsets (start the search from the functionCallExp) // SgExprListExp* exprListExp = functionCallExpression->get_args(); // ROSE_ASSERT (exprListExp != NULL); // // SgExpressionPtrList & expressionPtrList = exprListExp->get_expressions(); // SgExpressionPtrList::iterator i = expressionPtrList.begin(); // // // Case of indexing objects used within operator() // int counter = 0; // while (i != expressionPtrList.end()) { // // printf ("Looking for the offset on #%d of %d (total) \n",counter,expressionPtrList.size()); // // // Build up the name of the final index variable (or at least give // // it a unique number by dimension) // string counterString = StringUtility::numberToString(counter + 1); // // // Call another transformation mechanism to generate string for the index // // expression (since we don't have an unparser mechanism in ROSE yet) // indexOffsetString[counter] = IndexOffsetQuery::transformation(*i); // // ROSE_ASSERT (indexOffsetString[counter].c_str() != NULL); // // printf ("indexOffsetString [%d] = %s \n",counter,indexOffsetString[counter].c_str()); // // // Accumulate a list of all the InternalIndex, Index, and Range objects // printf(" Warning - Need to handle indexNameList from the older code \n"); // // i++; // counter++; // } // Added VAR_REF case (moved from the local function) case VAR_REF: { // A VAR_REF has to output a string (the variable name) #if DEBUG printf ("Found a variable reference expression \n"); #endif // Since we are at a leaf in the traversal of the AST this attribute list should a size of 0. ROSE_ASSERT(synthesizedAttributeList.size() == 0); SgVarRefExp* varRefExp = isSgVarRefExp(astNode); ROSE_ASSERT(varRefExp != NULL); SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT(initializedName != NULL); SgName variableName = initializedName->get_name(); string buffer; string indexOffsetString; // Now compute the offset to the index objects (form a special query for this???) SgType* type = variableSymbol->get_type(); ROSE_ASSERT(type != NULL); string typeName = TransformationSupport::getTypeName(type); ROSE_ASSERT(typeName.c_str() != NULL); // Recognize only these types at present if (typeName == "intArray" || typeName == "floatArray" || typeName == "doubleArray") { // Only define the variable name if we are using an object of array type // Copy the string from the SgName object to a string object string variableNameString = variableName.str(); #if DEBUG printf("Handle case of A++ array object VariableName: %s \n", variableNameString.c_str()); #endif if (arrayAssignmentStatementQueryInheritedData.arrayStatementDimensionDefined == TRUE) { cout << " Dim: " << arrayAssignmentStatementQueryInheritedData.arrayStatementDimension << endl; // The the globally computed array dimension from the arrayAssignmentStatementQueryInheritedData dimensionList.push_back(arrayAssignmentStatementQueryInheritedData.arrayStatementDimension); } else { dimensionList.push_back(6); // Default dimension for A++/P++ } nodeList.push_back(isSgExpression(varRefExp)); //processArrayRefExp(varRefExp, arrayAssignmentStatementQueryInheritedData); // Setup an intry in the synthesized attribute data base for this variable any // future results from analysis could be place there at this point as well // record the name in the synthesized attribute ROSE_ASSERT(operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess); ArrayOperandDataBase arrayOperandDB = operandDataBase.setVariableName(variableNameString); } break; } default: { break; } } // End of main switch statement #if DEBUG printf ("$$$$$ BOTTOM of arrayAssignmentStatementAssembly::evaluateSynthesizedAttribute (astNode = %s) \n",astNode->sage_class_name()); printf (" BOTTOM: returnString = \n%s \n",returnString.c_str()); #endif return returnSynthesizedAttribute; }
ParallelContainerQuerySynthesizedAttribute ParallelContainerQueryTraversal::evaluateSynthesizedAttribute ( SgNode* astNode, ParallelContainerQueryInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { ParallelContainerQuerySynthesizedAttribute returnAttribute; // printf ("In evaluateSynthesizedAttribute: (astNode->sage_class_name() = %s) \n", // astNode->sage_class_name()); switch(astNode->variantT()) { case V_SgForStatement: { bool isValidForLoopInitializer = synthesizedAttributeList[SgForStatement_for_init_stmt].validInitializer; // DQ (11/28/2005): The interface to SgForStatement has been changed to allow for tests to be a SgStatement (declaration) // bool isValidForLoopTest = synthesizedAttributeList[SgForStatement_test_expr_root].validTestExpression; bool isValidForLoopTest = synthesizedAttributeList[SgForStatement_test].validTestExpression; bool isValidForLoopIncrement = synthesizedAttributeList[SgForStatement_increment_expr_root].validIncrementExpression; bool isValidForLoopHeader = isValidForLoopInitializer && isValidForLoopTest && isValidForLoopIncrement; bool isValidForLoopBody = synthesizedAttributeList[SgForStatement_loop_body].validLoopBody; // printf ("isValidForLoopInitializer = %s \n",isValidForLoopInitializer ? "true" : "false"); // printf ("isValidForLoopTest = %s \n",isValidForLoopTest ? "true" : "false"); // printf ("isValidForLoopIncrement = %s \n",isValidForLoopIncrement ? "true" : "false"); // printf ("isValidForLoopHeader = %s \n",isValidForLoopHeader ? "true" : "false"); // printf ("isValidForLoopBody = %s \n",isValidForLoopBody ? "true" : "false"); returnAttribute.validParallelTransformation = isValidForLoopHeader && isValidForLoopBody; break; } case V_SgFunctionCallExp: { // printf ("Found the SgFunctionCallExp \n"); SgFunctionCallExp* functionCall = isSgFunctionCallExp(astNode); ROSE_ASSERT (functionCall != NULL); string functionName = TransformationSupport::getFunctionName(functionCall); string className = TransformationSupport::getFunctionTypeName(functionCall); // printf ("className = %s function name = %s \n",className.c_str(),functionName.c_str()); if (inheritedAttribute.inInitializer == true) { // initalizer should be either "list::iterator i = list.begin()" or "i = list.begin()" // printf ("Found the SgFunctionCallExp in the for loop initializer \n"); OpenMP_Translation_Utility::AbstractionListType l = containerInfoList->matchingContainerNameList (className); ROSE_ASSERT (l.size() > 0); ROSE_ASSERT (functionName == "begin"); returnAttribute.validInitializer = true; } if (inheritedAttribute.inTestExpression == true) { // test expression should be "iter != mylist.end()" // printf ("Found the SgFunctionCallExp in the for loop test expression \n"); if (className != "iterator") { // Don't test iterator member functions, typically "operator!=()" OpenMP_Translation_Utility::AbstractionListType l = containerInfoList->matchingContainerNameList (className); ROSE_ASSERT (l.size() > 0); ROSE_ASSERT (functionName == "end"); returnAttribute.validTestExpression = true; } else { // need to pass along the synthesized attribute information for (unsigned int i=0; i < synthesizedAttributeList.size(); i++) { returnAttribute.validTestExpression = returnAttribute.validTestExpression || synthesizedAttributeList[i].validTestExpression; } } } if (inheritedAttribute.inIncrementExpression == true) { // This expression should just be "i++", so likely there is something wrong here // (unless it is the operator++() member function) // printf ("Found the SgFunctionCallExp in the for loop increment expression \n"); ROSE_ASSERT (functionName == "operator++"); returnAttribute.validIncrementExpression = true; } if (inheritedAttribute.inLoopBody == true) { // Make sure it is a function from the target library // printf ("Found the SgFunctionCallExp in the for loop body \n"); if (className != "iterator") { OpenMP_Translation_Utility::AbstractionListType l = containerInfoList->matchingFunctionNameList (functionName); ROSE_ASSERT (l.size() > 0); returnAttribute.validLoopBody = true; } } break; } default: { // Merge allthe child attributes to a single synthesized attribute for (unsigned int i=0; i < synthesizedAttributeList.size(); i++) { returnAttribute.validInitializer = returnAttribute.validInitializer || synthesizedAttributeList[i].validInitializer; returnAttribute.validTestExpression = returnAttribute.validTestExpression || synthesizedAttributeList[i].validTestExpression; returnAttribute.validIncrementExpression = returnAttribute.validIncrementExpression || synthesizedAttributeList[i].validIncrementExpression; returnAttribute.validLoopBody = returnAttribute.validLoopBody || synthesizedAttributeList[i].validLoopBody; returnAttribute.validParallelTransformation = returnAttribute.validParallelTransformation || synthesizedAttributeList[i].validParallelTransformation; } } } return returnAttribute; }
Detection_SynthesizedAttribute DetectionTraversal::evaluateSynthesizedAttribute (SgNode* astNode, Detection_InheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { ROSE_ASSERT(astNode != NULL); Detection_SynthesizedAttribute return_synthesizedAttribute(astNode); #if 1 printf ("In evaluateSynthesizedAttribute(): astNode = %p = %s synthesizedAttributeList.size() = %zu dslChildren.size() = %zu \n", astNode,astNode->class_name().c_str(),synthesizedAttributeList.size(),return_synthesizedAttribute.dslChildren.size()); #endif // At each IR node and across all children, accumulate the dslChildren (child nodes for each of the DSL AST nodes). for (SubTreeSynthesizedAttributes::iterator i = synthesizedAttributeList.begin(); i != synthesizedAttributeList.end(); i++) { SgNode* childNode = (*i).node; // ROSE_ASSERT(childNode != NULL); if (childNode != NULL) { #if 0 printf ("Identified child node in evaluateSynthesizedAttribute(): childNode = %p = %s \n",childNode,childNode->class_name().c_str()); #endif // Insert each list from the child into the accumulated list in the current Synthesized Attribute. return_synthesizedAttribute.dslChildren.insert(return_synthesizedAttribute.dslChildren.end(),i->dslChildren.begin(),i->dslChildren.end()); #if 0 printf (" --- copying i->dslChildren.size() = %zu into return_synthesizedAttribute.dslChildren.size() = %zu \n",i->dslChildren.size(),return_synthesizedAttribute.dslChildren.size()); #endif if (return_synthesizedAttribute.dslChildren.empty() == false) { #if 0 printf ("In evaluateSynthesizedAttribute(): dslChildren.size() = %zu \n",return_synthesizedAttribute.dslChildren.size()); #endif } } else { #if 1 printf ("childNode == NULL \n"); #endif } } // Recognition of other control statements (e.g. for loops for the stencil evaluation) or expression/statement abstractions (e.g. function calls) // Note: DSL specific control abstractions might be recognised as loops containing DSL abstractions and having constant evaluatable base and bounds. // For any DSL specific AST nodes (C++ AST nodes containing a DSL_Attribute), initialize the pointers to children of the DSL IR node. AstAttributeMechanism* astAttributeContainer = astNode->get_attributeMechanism(); if (astAttributeContainer != NULL) { #if 1 printf ("In evaluateSynthesizedAttribute(): found a attribute on astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif // I think there should only be one DSL attribute, in the future we can support more on a single IR node. if (astAttributeContainer->size() != 1) { printf ("WARNING: astAttributeContainer->size() != 1: astAttributeContainer->size() = %zu \n",astAttributeContainer->size()); } #if 1 // DQ: Allow this for the moment while testing. ROSE_ASSERT(astAttributeContainer->size() == 1); #endif // Loop over all the attributes at this IR node // Pei-Hung (12/22/15): THe ASTAttributeMechanmsim is changed and has to use new API // for (AstAttributeMechanism::iterator i = astAttributeContainer->begin(); i != astAttributeContainer->end(); i++) BOOST_FOREACH (const std::string &attributeName, astAttributeContainer->getAttributeIdentifiers()) { AstAttribute* attribute = astNode->getAttribute(attributeName); ROSE_ASSERT(attribute != NULL); #if 1 // DSL_Attribute* dslAstAttribute = dynamic_cast<DSL_Attribute*>(attribute); dsl_attribute* dslAstAttribute = dynamic_cast<dsl_attribute*>(attribute); ROSE_ASSERT(dslAstAttribute != NULL); #if 1 printf ("Identified dslAstAttribute in evaluateSynthesizedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); printf (" --- return_synthesizedAttribute.dslChildren.size() = %zu \n",return_synthesizedAttribute.dslChildren.size()); #endif // Copy the dsl child data to the dsl attribute. dslAstAttribute->currentNode = astNode; dslAstAttribute->dslChildren = return_synthesizedAttribute.dslChildren; #endif } // Clear the dsl attributes becasue we the only collect dsl child attributes at dsl attributed IR nodes and don't pass then further up the tree. return_synthesizedAttribute.dslChildren.clear(); // Add the current node since it has an attribute. return_synthesizedAttribute.dslChildren.push_back(astNode); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif }
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; }
MySynthesizedAttribute MyTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { MySynthesizedAttribute returnAttribute; switch(astNode->variantT()) { case V_SgVarRefExp: { cout << " found V_SgVarRefExp " << astNode->unparseToString() << endl; if(mReplaceVariable) { if( ( strcmp( astNode->unparseToString().c_str(), VARIABLE_NAME )==0 ) && ( isSgTypeInt(isSgVarRefExp(astNode)->get_type()) ) ) { returnAttribute.setVarRefFound( true ); AstRestructure::unparserReplace( isSgVarRefExp(astNode), "newInt" ); cout << " replacing with 'newInt' " << endl; } } } break; case V_SgVariableDeclaration: { SgVariableDeclaration *varDecl = isSgVariableDeclaration(astNode); cout << " found V_SgVariableDeclaration " << astNode->unparseToString() << endl; // replace only integer variables called "i" if( (varDecl->get_traversalSuccessorContainer().size() > 0) && isSgInitializedName( varDecl->get_traversalSuccessorContainer()[0]) && ( strcmp(isSgInitializedName(varDecl->get_traversalSuccessorContainer()[0])->get_name().str(), VARIABLE_NAME )==0 ) && ( isSgTypeInt(isSgInitializedName(varDecl->get_traversalSuccessorContainer()[0])->get_type()) ) ) { // found declaration of "int i" string newDeclaration("int newInt = i + 100;"); returnAttribute.insert( varDecl, newDeclaration, HighLevelCollectionTypedefs::LocalScope, HighLevelCollectionTypedefs::AfterCurrentPosition ); assert( mReplaceVariable==0 ); // if it's true, there is another "int i", and this transformation wont work... mReplaceVariable = 1; cout << " inserted: '" << newDeclaration <<"' , starting variable replacement " << endl; } } break; default: break; } // node type bool synth = false; for( SubTreeSynthesizedAttributes::iterator i=synthesizedAttributeList.begin(); i!= synthesizedAttributeList.end(); i++ ) { if( (*i).getVarRefFound() ) synth = true; } if( synth ) { returnAttribute.setVarRefFound( true ); if(isSgStatement( astNode )) { cout << " new statement " << " : '" << astNode->unparseToString() << "' " << endl; returnAttribute.setVarRefFound( false ); //if(!isSgReturnStmt( astNode )) { // DEBUG, this should work!??!? returnAttribute.replace( astNode, astNode->unparseToString(), HighLevelCollectionTypedefs::LocalScope ); //} } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable--; cerr << "end of scope " << mReplaceVariable << endl; } } return returnAttribute; }
MySynthesizedAttribute MyTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { MySynthesizedAttribute returnAttribute; switch(astNode->variantT()) { case V_SgForStatement: { SgForStatement *forStat = isSgForStatement(astNode); cout << " found V_SgForStatement " << printPosition(astNode) << "" << endl; for(size_t i=0; i<mAllFors.size(); i++) { if((mAllFors[i]->blocked)&&(astNode == mAllFors[i]->forStmt)) { ostringstream newFor; newFor << "for("; newFor << (*(forStat->get_init_stmt().begin()))->unparseToString(); newFor << forStat->get_test_expr()->unparseToString() << ";" ; newFor << mAllFors[i]->varName << "+=" << mAllFors[i]->blockSize << ")\n" ; newFor << forStat->get_loop_body()->unparseToString(); cout << " is blocked loop..." << endl; returnAttribute.replace( astNode, newFor.str() ); } } } break; case V_SgVarRefExp: { cout << " found V_SgVarRefExp " << printPosition(astNode) << astNode->unparseToString() << endl; forBlockVector fors = inheritedAttribute.getForScopes(); // replace variable occurrences in the loop kernel if(inheritedAttribute.getLoopKernel()) { for(size_t i=0;i<fors.size(); i++) { if( ( strcmp( astNode->unparseToString().c_str(), fors[i]->varName.c_str() )==0 ) && ( isSgVarRefExp(astNode)->get_type() == fors[i]->varType ) ) { string blockedVarName("blocked_"); blockedVarName += fors[i]->varName; AstRestructure::unparserReplace( isSgVarRefExp(astNode), blockedVarName ); cout << " replacing with '"<<blockedVarName<<"' " << endl; } } } } break; default: break; } // node type bool synth = false; for( SubTreeSynthesizedAttributes::iterator i=synthesizedAttributeList.begin(); i!= synthesizedAttributeList.end(); i++ ) { if( (*i).getVarRefFound() ) synth = true; } if( synth ) { returnAttribute.setVarRefFound( true ); if(isSgStatement( astNode )) { cout << " new statement " << printPosition(astNode) << " : '" << astNode->unparseToString() << "' " << endl; returnAttribute.setVarRefFound( false ); //if(!isSgReturnStmt( astNode )) { // DEBUG, this should work!??!? returnAttribute.replace( astNode, astNode->unparseToString(), HighLevelCollectionTypedefs::LocalScope ); //} } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable--; cerr << "end of scope " << mReplaceVariable << endl; } } //if(astNode == mpLoopBody) { // FIXME why doesnt replace basic block work? if( (astNode->get_parent() == mpLoopBody)&&(inheritedAttribute.getLoopKernel()) ) { // we're back at the loop kernel block, now replace and insert new loops... insertTransformedLoopBody( astNode, returnAttribute, inheritedAttribute.getForScopes() ); } return returnAttribute; }