/** * \brief Return true if methodDecl overrides virtualMethodDecl. * \param methodDecl a method declaration. * \param virtualMethodDecl a method declaration. * \return Returns true if virtualMethodDecl is declared as a virtual * method and methodDecl has the same type signature and name * as virtualMethodDecl. * * NB: It is assumed that the class defining virtualMethodDecl is a base * class of the class defining methodDecl. */ bool methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, SgMemberFunctionDeclaration *virtualMethodDecl) { if ( !isVirtual(virtualMethodDecl) ) return false; #if 1 // Hmmm ... couldn't we just compare mangled names? return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() ); #else if ( methodDecl->get_name() != virtualMethodDecl->get_name() ) return false; SgType *methodReturnType = methodDecl->get_orig_return_type(); SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type(); if ( methodReturnType != virtualMethodReturnType ) return false; int numMethodParams = 0; int numVirtualMethodParams = 0; SgFunctionParameterList *methodParameterList = methodDecl->get_parameterList(); if (methodParameterList != NULL) { numMethodParams = methodParameterList->get_args().size(); } SgFunctionParameterList *virtualMethodParameterList = virtualMethodDecl->get_parameterList(); if (virtualMethodParameterList != NULL) { numVirtualMethodParams = virtualMethodParameterList->get_args().size(); } if ( numMethodParams != numVirtualMethodParams ) return false; if ( numMethodParams == 0 ) return true; const SgInitializedNamePtrList &methodFormalParams = methodParameterList->get_args(); const SgInitializedNamePtrList &virtualMethodFormalParams = virtualMethodParameterList->get_args(); SgInitializedNamePtrList::const_iterator methodIt; SgInitializedNamePtrList::const_iterator virtualMethodIt; for(methodIt = methodFormalParams.begin(), virtualMethodIt = virtualMethodFormalParams.begin(); methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { SgInitializedName* methodFormalParam = *methodIt; ROSE_ASSERT(methodFormalParam != NULL); SgInitializedName* virtualMethodFormalParam = *virtualMethodIt; ROSE_ASSERT(virtualMethodFormalParam != NULL); if ( methodFormalParam->get_type() != virtualMethodFormalParam->get_type() ) return false; } return true; #endif }
SgName Unparser_Nameq::generateNameQualifierSupport ( SgScopeStatement* scope, const SgUnparse_Info& info, bool qualificationOfType ) { // DQ (5/28/2011): We need this information to be passed in from the outside (qualificationOfType): // qualificationOfName == true implies this is name qualification for a name vs a type. // qualificationOfName == false implies this is name qualification for a type. // note that the complete minimally qualified name is stored and retrieved from the map using // either SgNode::get_globalQualifiedNameMapForNames() or SgNode::get_globalQualifiedNameMapForTypes(). // bool qualificationOfType = false; SgName qualifiedName; // If the name qualification length required is zero then we can return an empty string and avoid the logic below. if (info.get_name_qualification_length() > 0) { // DQ (5/28/2011): Adding support for qualified name lookup. SgNode* nameQualificationReferenceNode = info.get_reference_node_for_qualification(); if (nameQualificationReferenceNode != NULL) { if (qualificationOfType == false) { std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForNames().find(nameQualificationReferenceNode); if (i != SgNode::get_globalQualifiedNameMapForNames().end()) { qualifiedName = i->second; } else { printf ("key not found in node map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str()); ROSE_ASSERT(false); } } else { std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForTypes().find(nameQualificationReferenceNode); if (i != SgNode::get_globalQualifiedNameMapForTypes().end()) { qualifiedName = i->second; } else { // Debugging support... printf ("key not found in type map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str()); // Extra Debugging support... switch(nameQualificationReferenceNode->variantT()) { case V_SgInitializedName: { SgInitializedName* initializedName = isSgInitializedName(nameQualificationReferenceNode); printf ("initializedName = %s \n",initializedName->get_name().str()); break; } default: { printf ("Default reached in switch(nameQualificationReferenceNode->variantT()) \n"); ROSE_ASSERT(false); } } ROSE_ASSERT(false); } } } else { // This should be an error. printf ("Error: nameQualificationReferenceNode == NULL but info.get_name_qualification_length() = %d \n",info.get_name_qualification_length()); ROSE_ASSERT(false); } } else { // printf ("return empty qualified name since info.get_name_qualification_length() == 0 \n"); } return qualifiedName; }
// Constructs _A_pointer[SC_A(_1,_2)] SgPntrArrRefExp* buildAPPArrayRef(SgNode* astNode, ArrayAssignmentStatementQueryInheritedAttributeType & arrayAssignmentStatementQueryInheritedData, OperandDataBaseType & operandDataBase, SgScopeStatement* scope, SgExprListExp* parameterExpList) { #if DEBUG printf("Contructing A++ array reference object \n"); #endif string returnString; 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(); vector<SgExpression*> parameters; // Figure out the dimensionality of the statement globally int maxNumberOfIndexOffsets = 6; // default value for A++/P++ arrays ROSE_ASSERT(arrayAssignmentStatementQueryInheritedData.arrayStatementDimensionDefined == TRUE); if (arrayAssignmentStatementQueryInheritedData.arrayStatementDimensionDefined == TRUE) { // The the globally computed array dimension from the arrayAssignmentStatementQueryInheritedData maxNumberOfIndexOffsets = arrayAssignmentStatementQueryInheritedData.arrayStatementDimension; } // Then we want the minimum of all the dimensions accesses (or is it the maximum?) for (int n = 0; n < maxNumberOfIndexOffsets; n++) { parameters.push_back(buildVarRefExp("_" + StringUtility::numberToString(n + 1), scope)); } // Make a reference to the global operand database //OperandDataBaseType & operandDataBase = accumulatorValue.operandDataBase; SgType* type = variableSymbol->get_type(); ROSE_ASSERT(type != NULL); string typeName = TransformationSupport::getTypeName(type); ROSE_ASSERT(typeName.c_str() != NULL); // Copy the string from the SgName object to a string object string variableNameString = variableName.str(); // 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); // We could have specified in the inherited attribute that this array variable was // index and if so leave the value of $IDENTIFIER_STRING to be modified later in // the assembly of the operator() and if not do the string replacement on // $IDENTIFIER_STRING here (right now). returnString = string("$IDENTIFIER_STRING") + string("_pointer[SC") + string("$MACRO_NAME_SUBSTRING") + string("(") + string("$OFFSET") + string(")]"); string functionSuffix = ""; SgPntrArrRefExp* pntrRefExp; cout << " arrayAssignmentStatementQueryInheritedData.getIsIndexedArrayOperand() " << arrayAssignmentStatementQueryInheritedData.getIsIndexedArrayOperand() << endl; // The inherited attribute mechanism is not yet implimented if (arrayAssignmentStatementQueryInheritedData.getIsIndexedArrayOperand() == FALSE) //if(true) { // do the substitution of $OFFSET here since it our last chance // (offsetString is the list of index values "index1,index2,...,indexn") //returnString = StringUtility::copyEdit(returnString,"$OFFSET",offsetString); string operandIdentifier = arrayOperandDB.generateIdentifierString(); // do the substitution of $IDENTIFIER_STRING here since it our last chance // if variable name is "A", generate: A_pointer[SC_A(index1,...)] // returnString = StringUtility::copyEdit (returnString,"$IDENTIFIER_STRING",variableNameString); ROSE_ASSERT(arrayOperandDB.indexingAccessCode > ArrayTransformationSupport::UnknownIndexingAccess); // Edit into place the name of the data pointer returnString = StringUtility::copyEdit(returnString, "$IDENTIFIER_STRING", operandIdentifier); // Optimize the case of uniform or unit indexing to generate a single subscript macro definition if ((arrayOperandDB.indexingAccessCode == ArrayTransformationSupport::UniformSizeUnitStride) || (arrayOperandDB.indexingAccessCode == ArrayTransformationSupport::UniformSizeUniformStride)) returnString = StringUtility::copyEdit(returnString, "$MACRO_NAME_SUBSTRING", ""); else { returnString = StringUtility::copyEdit(returnString, "$MACRO_NAME_SUBSTRING", operandIdentifier); functionSuffix = operandIdentifier; } /* * Create SgPntrArrRefExp lhs is VarRefExp and rhs is SgFunctionCallExp */ SgVarRefExp* newVarRefExp = buildVarRefExp(operandIdentifier + "_pointer", scope); string functionName = "SC" + functionSuffix; SgFunctionCallExp* functionCallExp; if (parameterExpList == NULL) functionCallExp = buildFunctionCallExp(functionName, buildIntType(), buildExprListExp(parameters), scope); else functionCallExp = buildFunctionCallExp(functionName, buildIntType(), parameterExpList, scope); pntrRefExp = buildPntrArrRefExp(newVarRefExp, functionCallExp); #if DEBUG cout << " pntrArrRefExp = " << pntrRefExp->unparseToString() << endl; #endif } return pntrRefExp; }
void runAnalyses(SgProject* root, Labeler* labeler, VariableIdMapping* variableIdMapping) { SPRAY::DFAnalysisBase::normalizeProgram(root); if(option_fi_constanalysis) { VarConstSetMap varConstSetMap; FIConstAnalysis fiConstAnalysis(variableIdMapping); fiConstAnalysis.runAnalysis(root); fiConstAnalysis.attachAstAttributes(labeler,"const-analysis-inout"); // not iolabeler if(csvConstResultFileName) { cout<<"INFO: generating const CSV file "<<option_prefix+csvConstResultFileName<<endl; fiConstAnalysis.writeCvsConstResult(*variableIdMapping, option_prefix+csvConstResultFileName); } cout << "INFO: annotating analysis results as comments."<<endl; AstAnnotator ara(labeler); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "const-analysis-inout"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "const-analysis-inout"); } if(option_at_analysis) { cout<<"STATUS: running address taken analysis."<<endl; cout << "STATUS: computing variable and function mappings."<<endl; // compute variableId mappings VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(root); // Compute function id mappings: FunctionIdMapping functionIdMapping; functionIdMapping.computeFunctionSymbolMapping(root); if(option_trace) { std::cout << std::endl << "TRACE: Variable Id Mapping:" << std::endl; variableIdMapping.toStream(std::cout); std::cout << std::endl << "TRACE: Function Id Mapping:" << std::endl; functionIdMapping.toStream(std::cout); } cout << "STATUS: computing address taken sets."<<endl; SPRAY::FIPointerAnalysis fipa(&variableIdMapping, &functionIdMapping, root); fipa.initialize(); fipa.run(); //cout << "STATUS: computed address taken sets:"<<endl; //fipa.getFIPointerInfo()->printInfoSets(); bool createCsv = false; ofstream addressTakenCsvFile; if(csvAddressTakenResultFileName) { std::string addressTakenCsvFileName = option_prefix; addressTakenCsvFileName += csvAddressTakenResultFileName; addressTakenCsvFile.open(addressTakenCsvFileName.c_str()); createCsv = true; } cout << "INFO: annotating declarations of address taken variables and functions."<<endl; // Annotate declarations/definitions of variables from which the address was taken: VariableIdSet addressTakenVariableIds = fipa.getAddressTakenVariables(); for(VariableIdSet::const_iterator idIter = addressTakenVariableIds.begin(); idIter != addressTakenVariableIds.end(); ++idIter) { // Determine the variable declaration/definition: SgLocatedNode* decl = variableIdMapping.getVariableDeclaration(*idIter); if(!decl) { // The current variable is presumably a function parameter: Try to get the initialized name: SgVariableSymbol* varSymbol = isSgVariableSymbol(variableIdMapping.getSymbol(*idIter)); ROSE_ASSERT(varSymbol); SgInitializedName* paramDecl = isSgInitializedName(varSymbol->get_declaration()); // We should not have a real variable declaration for the parameter: ROSE_ASSERT(isSgFunctionParameterList(paramDecl->get_declaration())); // Use the InitializedName: decl = paramDecl; } if(decl) { // Create the comment: ostringstream commentStream; commentStream << "/* Address of \"" << variableIdMapping.variableName(*idIter) << "\" is " << "presumably taken.*/"; // Annotate first declaration: insertComment(commentStream.str(), PreprocessingInfo::before, decl); // TODO: Annotate other declarations too! // Annotate definition if available (e.g. not available in case of parameter): if(SgDeclarationStatement* variableDeclaration = isSgDeclarationStatement(decl)) { if(SgDeclarationStatement* definingDeclaration = variableDeclaration->get_definingDeclaration()) { insertComment(commentStream.str(), PreprocessingInfo::before, definingDeclaration); } } if(createCsv) { // Write variable info to csv: addressTakenCsvFile << VariableId::idKindIndicator << "," // The id of the variable (id codes are influenced by the used system headers // and are therefore not stable/portable): << (option_csv_stable ? string("<unstable>") : int_to_string((*idIter).getIdCode())) << "," // Name of the variable: << variableIdMapping.variableName(*idIter) << "," // TODO: Mangled scope and type are currently not stable/portable // (see comments in getScopeAsMangledStableString(...)) // Mangled type of the variable (non-mangled type may contain commas (e.g. "A<int,bool>"): << (option_csv_stable ? string("<unstable>") : variableIdMapping.getType(*idIter)->get_mangled().getString()) << "," // Mangled scope of the variable: << (option_csv_stable ? string("<unstable>") : getScopeAsMangledStableString(decl)) << "," // Is the address taken? (currently only address taken variables are output to csv) << "1" << endl; } } else { cout << "ERROR: No declaration for " << variableIdMapping.uniqueShortVariableName(*idIter) << " available." << endl; ROSE_ASSERT(false); } } // Annotate declarations and definitions of functions from which the address was taken: FunctionIdSet addressTakenFunctionIds = fipa.getAddressTakenFunctions(); for(FunctionIdSet::const_iterator idIter = addressTakenFunctionIds.begin(); idIter != addressTakenFunctionIds.end(); ++idIter) { if(SgFunctionDeclaration* decl = functionIdMapping.getFunctionDeclaration(*idIter)) { // Create the comment: ostringstream commentStream; commentStream << "/* Address of \"" << functionIdMapping.getFunctionNameFromFunctionId(*idIter) << "(...)\" is " << "presumably taken.*/"; // Annotate first declaration: insertComment(commentStream.str(), PreprocessingInfo::before, decl); // TODO: Annotate other declarations too! // Annotate definition if available: if(SgDeclarationStatement* definingDeclaration = decl->get_definingDeclaration()) { insertComment(commentStream.str(), PreprocessingInfo::before, definingDeclaration); } if(createCsv) { addressTakenCsvFile << FunctionId::idKindIndicator << "," // The id of the function (id codes are influenced by the used system headers // and are therefore not stable/portable): << (option_csv_stable ? string("<unstable>") : int_to_string((*idIter).getIdCode())) << "," // Name of the function: << functionIdMapping.getFunctionNameFromFunctionId(*idIter) << "," // TODO: Mangled scope and type are currently not stable/portable // (see comments in getScopeAsMangledStableString(...)) // Mangled type of the function (non-mangled type may contain commas (e.g. "void (A<int,bool>)"): << (option_csv_stable ? string("<unstable>") : functionIdMapping.getTypeFromFunctionId(*idIter)->get_mangled().getString()) << "," // Mangled scope of the function: << (option_csv_stable ? string("<unstable>") :getScopeAsMangledStableString(decl)) << "," // Is the address taken? (currently only address taken functions are output to csv) << "1" << endl; } } else { cout << "ERROR: No declaration for " << functionIdMapping.getUniqueShortNameFromFunctionId(*idIter) << " available." << endl; ROSE_ASSERT(false); } } if(createCsv) { addressTakenCsvFile.close(); } #if 0 VariableIdSet vidset=fipa.getModByPointer(); cout<<"mod-set: "<<SPRAY::VariableIdSetPrettyPrint::str(vidset,variableIdMapping)<<endl; #endif } if(option_interval_analysis) { cout << "STATUS: creating interval analyzer."<<endl; SPRAY::IntervalAnalysis* intervalAnalyzer=new SPRAY::IntervalAnalysis(); cout << "STATUS: initializing interval analyzer."<<endl; intervalAnalyzer->setNoTopologicalSort(option_no_topological_sort); intervalAnalyzer->initialize(root); cout << "STATUS: running pointer analysis."<<endl; ROSE_ASSERT(intervalAnalyzer->getVariableIdMapping()); SPRAY::FIPointerAnalysis* fipa=new FIPointerAnalysis(intervalAnalyzer->getVariableIdMapping(), intervalAnalyzer->getFunctionIdMapping(), root); fipa->initialize(); fipa->run(); intervalAnalyzer->setPointerAnalysis(fipa); cout << "STATUS: initializing interval transfer functions."<<endl; intervalAnalyzer->initializeTransferFunctions(); cout << "STATUS: initializing interval global variables."<<endl; intervalAnalyzer->initializeGlobalVariables(root); intervalAnalyzer->setSolverTrace(option_trace); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); intervalAnalyzer->determineExtremalLabels(startFunRoot); intervalAnalyzer->run(); #if 0 intervalAnalyzer->attachInInfoToAst("iv-analysis-in"); intervalAnalyzer->attachOutInfoToAst("iv-analysis-out"); AstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "iv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "iv-analysis-out"); #else AnalysisAstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"iv-analysis",intervalAnalyzer); #endif if(option_check_static_array_bounds) { checkStaticArrayBounds(root,intervalAnalyzer); } // schroder3 (2016-08-08): Generate csv-file that contains unreachable statements: if(csvDeadCodeUnreachableFileName) { // Generate file name and open file: std::string deadCodeCsvFileName = option_prefix; deadCodeCsvFileName += csvDeadCodeUnreachableFileName; ofstream deadCodeCsvFile; deadCodeCsvFile.open(deadCodeCsvFileName.c_str()); // Iteratate over all CFG nodes/ labels: for(Flow::const_node_iterator i = intervalAnalyzer->getFlow()->nodes_begin(); i != intervalAnalyzer->getFlow()->nodes_end(); ++i) { const Label& label = *i; // Do not output a function call twice (only the function call label and not the function call return label): if(!intervalAnalyzer->getLabeler()->isFunctionCallReturnLabel(label)) { /*const*/ IntervalPropertyState& intervalsLattice = *static_cast<IntervalPropertyState*>(intervalAnalyzer->getPreInfo(label.getId())); if(intervalsLattice.isBot()) { // Unreachable statement found: const SgNode* correspondingNode = intervalAnalyzer->getLabeler()->getNode(label); ROSE_ASSERT(correspondingNode); // Do not output scope statements ({ }, ...) if(!isSgScopeStatement(correspondingNode)) { deadCodeCsvFile << correspondingNode->get_file_info()->get_line() << "," << SPRAY::replace_string(correspondingNode->unparseToString(), ",", "/*comma*/") << endl; } } } } deadCodeCsvFile.close(); } delete fipa; } if(option_lv_analysis) { cout << "STATUS: creating LV analysis."<<endl; SPRAY::LVAnalysis* lvAnalysis=new SPRAY::LVAnalysis(); cout << "STATUS: initializing LV analysis."<<endl; lvAnalysis->setBackwardAnalysis(); lvAnalysis->setNoTopologicalSort(option_no_topological_sort); lvAnalysis->initialize(root); cout << "STATUS: running pointer analysis."<<endl; ROSE_ASSERT(lvAnalysis->getVariableIdMapping()); SPRAY::FIPointerAnalysis* fipa = new FIPointerAnalysis(lvAnalysis->getVariableIdMapping(), lvAnalysis->getFunctionIdMapping(), root); fipa->initialize(); fipa->run(); lvAnalysis->setPointerAnalysis(fipa); cout << "STATUS: initializing LV transfer functions."<<endl; lvAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing LV global variables."<<endl; lvAnalysis->initializeGlobalVariables(root); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); cout << "generating icfg_backward.dot."<<endl; write_file("icfg_backward.dot", lvAnalysis->getFlow()->toDot(lvAnalysis->getLabeler())); lvAnalysis->determineExtremalLabels(startFunRoot); lvAnalysis->run(); cout << "INFO: attaching LV-data to AST."<<endl; #if 0 lvAnalysis->attachInInfoToAst("lv-analysis-in"); lvAnalysis->attachOutInfoToAst("lv-analysis-out"); AstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "lv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "lv-analysis-out"); #else AnalysisAstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"lv-analysis",lvAnalysis); #endif // schroder3 (2016-08-15): Generate csv-file that contains dead assignments/ initializations: if(csvDeadCodeDeadStoreFileName) { // Generate file name and open file: std::string deadCodeCsvFileName = option_prefix; deadCodeCsvFileName += csvDeadCodeDeadStoreFileName; ofstream deadCodeCsvFile; deadCodeCsvFile.open(deadCodeCsvFileName.c_str()); if(option_trace) { cout << "TRACE: checking for dead stores." << endl; } // Iteratate over all CFG nodes/ labels: for(Flow::const_node_iterator labIter = lvAnalysis->getFlow()->nodes_begin(); labIter != lvAnalysis->getFlow()->nodes_end(); ++labIter) { const Label& label = *labIter; // Do not output a function call twice (only the function call return label and not the function call label): if(!lvAnalysis->getLabeler()->isFunctionCallLabel(label)) { /*const*/ SgNode* correspondingNode = lvAnalysis->getLabeler()->getNode(label); ROSE_ASSERT(correspondingNode); if(/*const*/ SgExprStatement* exprStmt = isSgExprStatement(correspondingNode)) { correspondingNode = exprStmt->get_expression(); } /*const*/ SgNode* association = 0; // Check if the corresponding node is an assignment or an initialization: if(isSgAssignOp(correspondingNode)) { association = correspondingNode; } else if(SgVariableDeclaration* varDecl = isSgVariableDeclaration(correspondingNode)) { SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDecl); ROSE_ASSERT(initName); // Check whether there is an initialization that can be eliminated (reference initialization can not be eliminated). if(!SgNodeHelper::isReferenceType(initName->get_type()) && initName->get_initializer()) { association = correspondingNode; } } if(association) { if(option_trace) { cout << endl << "association: " << association->unparseToString() << endl; } VariableIdSet assignedVars = AnalysisAbstractionLayer::defVariables(association, *lvAnalysis->getVariableIdMapping(), fipa); /*const*/ LVLattice& liveVarsLattice = *static_cast<LVLattice*>(lvAnalysis->getPreInfo(label.getId())); if(option_trace) { cout << "live: " << liveVarsLattice.toString(lvAnalysis->getVariableIdMapping()) << endl; cout << "assigned: " << endl; } bool minOneIsLive = false; for(VariableIdSet::const_iterator assignedVarIter = assignedVars.begin(); assignedVarIter != assignedVars.end(); ++assignedVarIter) { if(option_trace) { cout << (*assignedVarIter).toString(*lvAnalysis->getVariableIdMapping()) << endl; } if(liveVarsLattice.exists(*assignedVarIter)) { minOneIsLive = true; break; } } if(!minOneIsLive) { if(option_trace) { cout << "association is dead." << endl; } // assignment to only dead variables found: deadCodeCsvFile << correspondingNode->get_file_info()->get_line() << "," << SPRAY::replace_string(correspondingNode->unparseToString(), ",", "/*comma*/") << endl; } } } } deadCodeCsvFile.close(); } delete lvAnalysis; } if(option_rd_analysis) { cout << "STATUS: creating RD analyzer."<<endl; SPRAY::RDAnalysis* rdAnalysis=new SPRAY::RDAnalysis(); cout << "STATUS: initializing RD analyzer."<<endl; rdAnalysis->setNoTopologicalSort(option_no_topological_sort); rdAnalysis->initialize(root); cout << "STATUS: initializing RD transfer functions."<<endl; rdAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing RD global variables."<<endl; rdAnalysis->initializeGlobalVariables(root); cout << "generating icfg_forward.dot."<<endl; write_file("icfg_forward.dot", rdAnalysis->getFlow()->toDot(rdAnalysis->getLabeler())); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); rdAnalysis->determineExtremalLabels(startFunRoot); rdAnalysis->run(); cout << "INFO: attaching RD-data to AST."<<endl; rdAnalysis->attachInInfoToAst("rd-analysis-in"); rdAnalysis->attachOutInfoToAst("rd-analysis-out"); //printAttributes<RDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"rd-analysis-in"); cout << "INFO: annotating analysis results as comments."<<endl; ROSE_ASSERT(rdAnalysis->getVariableIdMapping()); #if 0 AstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "rd-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "rd-analysis-out"); #else AnalysisAstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"rd-analysis",rdAnalysis); #endif #if 0 cout << "INFO: substituting uses with rhs of defs."<<endl; substituteUsesWithAvailableExpRhsOfDef("ud-analysis", root, rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping()); #endif if(option_ud_analysis) { ROSE_ASSERT(option_rd_analysis); cout << "INFO: generating and attaching UD-data to AST."<<endl; createUDAstAttributeFromRDAttribute(rdAnalysis->getLabeler(),"rd-analysis-in", "ud-analysis"); Flow* flow=rdAnalysis->getFlow(); cout<<"Flow label-set size: "<<flow->nodeLabels().size()<<endl; CFAnalysis* cfAnalyzer0=rdAnalysis->getCFAnalyzer(); int red=cfAnalyzer0->reduceBlockBeginNodes(*flow); cout<<"INFO: eliminated "<<red<<" block-begin nodes in ICFG."<<endl; #if 0 cout << "INFO: computing program statistics."<<endl; ProgramStatistics ps(rdAnalysis->getVariableIdMapping(), rdAnalysis->getLabeler(), rdAnalysis->getFlow(), "ud-analysis"); ps.computeStatistics(); //ps.printStatistics(); cout << "INFO: generating resource usage visualization."<<endl; ps.setGenerateWithSource(false); ps.generateResourceUsageICFGDotFile("resourceusageicfg.dot"); flow->resetDotOptions(); #endif cout << "INFO: generating visualization data."<<endl; // generate ICFG visualization cout << "generating icfg.dot."<<endl; write_file("icfg.dot", flow->toDot(rdAnalysis->getLabeler())); // cout << "INFO: generating control dependence graph."<<endl; //Flow cdg=rdAnalysis->getCFAnalyzer()->controlDependenceGraph(*flow); cout << "generating datadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis0(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); //printAttributes<UDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"ud-analysis"); //ddvis._showSourceCode=false; // for large programs ddvis0.generateDefUseDotGraph(root,"datadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis1(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis1.includeFlowGraphEdges(flow); ddvis1.generateDefUseDotGraph(root,"icfgdatadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph_clustered.dot."<<endl; DataDependenceVisualizer ddvis2(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis2.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfgdatadependencegraph_clustered.dot",true); cout << "generating icfg_clustered.dot."<<endl; DataDependenceVisualizer ddvis3(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis3.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfg_clustered.dot",false); } } }
void runCurrentFile(vector<string> &argvList, bool debug, bool debug_map) { // Build the AST used by ROSE if (debug) std::cout << ">>>> Starting ROSE frontend ... " << endl; SgProject* project = frontend(argvList); if (debug) std::cout << ">>>> generate PDF " << endl; generatePDF ( *project ); if (debug) std::cout << ">>>> start def-use analysis ... " << endl; // Call the Def-Use Analysis DFAnalysis* defuse = new DefUseAnalysis(project); int val = defuse->run(debug); if (debug) std::cout << "Analysis is : " << (val ? "failure" : "success" ) << " " << val <<std::endl; if (val==1) exit(1); if (debug==false) defuse->dfaToDOT(); //example usage // testing NodeQuerySynthesizedAttributeType vars = NodeQuery::querySubTree(project, V_SgInitializedName); NodeQuerySynthesizedAttributeType::const_iterator i = vars.begin(); for (; i!=vars.end();++i) { SgInitializedName* initName = isSgInitializedName(*i); std::string name = initName->get_qualified_name().str(); vector<SgNode* > vec = defuse->getDefFor(initName, initName); if (vec.size()>0) if (debug) std::cout << " DEF>> Vector entries for " << name << " ( " << initName << " ) : " << vec.size() << std::endl; } // testing vars = NodeQuery::querySubTree(project, V_SgReturnStmt); i = vars.begin(); typedef std::vector <std::pair <SgInitializedName*, SgNode* > > maptype; for (; i!=vars.end();++i) { SgReturnStmt* ret = isSgReturnStmt(*i); ROSE_ASSERT(ret); maptype map = defuse->getUseMultiMapFor(ret); maptype::const_iterator j; j = map.begin(); for (; j!=map.end();++j) { SgInitializedName* initName = isSgInitializedName(j->first); ROSE_ASSERT(initName); std::string name = initName->get_qualified_name().str(); vector<SgNode* > vec = defuse->getUseFor(ret, initName); if (vec.size()>0) std::cout << " USE>> Vector entries for " << name << " ( " << ret << " ) : " << vec.size() << std::endl; } } // print resulting table if (debug_map) { cout << "\nDEFMAP" << endl; defuse->printDefMap(); cout << "\nUSEMAP" << endl; defuse->printUseMap(); } delete project; delete defuse; }
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; } }
int main( int argc, char * argv[] ) { // Option to linearize the array. Rose_STL_Container<std::string> localCopy_argv = CommandlineProcessing::generateArgListFromArgcArgv(argc, argv); int newArgc; char** newArgv = NULL; vector<string> argList = localCopy_argv; if (CommandlineProcessing::isOption(argList,"-f2c:","linearize",true) == true) { isLinearlizeArray = true; } CommandlineProcessing::generateArgcArgvFromList(argList,newArgc, newArgv); // Build the AST used by ROSE SgProject* project = frontend(newArgc,newArgv); AstTests::runAllTests(project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000,"_orig"); // Traversal with Memory Pool to search for variableDeclaration variableDeclTraversal translateVariableDeclaration; traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { /* For the Fortran AST, a single variableDeclaration can be shared by multiple variables. This violated the normalization rules for C unparser. Therefore, we have to transform it. */ SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); if((variableDeclaration->get_variables()).size() != 1) { updateVariableDeclarationList(variableDeclaration); statementList.push_back(variableDeclaration); removeList.push_back(variableDeclaration); } } // reset the vector that collects all variable declaration. We need to walk through memory pool again to find types variableDeclList.clear(); traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); SgInitializedNamePtrList initializedNameList = variableDeclaration->get_variables(); for(SgInitializedNamePtrList::iterator i=initializedNameList.begin(); i!=initializedNameList.end();++i) { SgInitializedName* initiallizedName = isSgInitializedName(*i); SgType* baseType = initiallizedName->get_type(); if(baseType->variantT() == V_SgArrayType) { SgArrayType* arrayBase = isSgArrayType(baseType); // At this moment, we are still working on the Fortran-stype AST. Therefore, there is no nested types for multi-dim array. if(arrayBase->findBaseType()->variantT() == V_SgTypeString) { arrayBase->reset_base_type(translateType(arrayBase->findBaseType())); arrayBase->set_rank(arrayBase->get_rank()+1); } } else { initiallizedName->set_type(translateType(baseType)); } } } // replace the AttributeSpecificationStatement Rose_STL_Container<SgNode*> AttributeSpecificationStatement = NodeQuery::querySubTree (project,V_SgAttributeSpecificationStatement); for (Rose_STL_Container<SgNode*>::iterator i = AttributeSpecificationStatement.begin(); i != AttributeSpecificationStatement.end(); i++) { SgAttributeSpecificationStatement* attributeSpecificationStatement = isSgAttributeSpecificationStatement(*i); ROSE_ASSERT(attributeSpecificationStatement); translateAttributeSpecificationStatement(attributeSpecificationStatement); statementList.push_back(attributeSpecificationStatement); removeList.push_back(attributeSpecificationStatement); } // replace the parameter reference parameterTraversal translateParameterRef; traverseMemoryPoolVisitorPattern(translateParameterRef); for(vector<SgVarRefExp*>::iterator i=parameterRefList.begin(); i!=parameterRefList.end(); ++i) { SgVarRefExp* parameterRef = isSgVarRefExp(*i); if(parameterSymbolList.find(parameterRef->get_symbol()) != parameterSymbolList.end()) { SgExpression* newExpr = isSgExpression(deepCopy(parameterSymbolList.find(parameterRef->get_symbol())->second)); ROSE_ASSERT(newExpr); newExpr->set_parent(parameterRef->get_parent()); replaceExpression(parameterRef, newExpr, false); } } /* Parameters will be replaced by #define, all the declarations should be removed */ for(map<SgVariableSymbol*,SgExpression*>::iterator i=parameterSymbolList.begin();i!=parameterSymbolList.end();++i) { SgVariableSymbol* symbol = i->first; SgInitializedName* initializedName = symbol->get_declaration(); SgVariableDeclaration* decl = isSgVariableDeclaration(initializedName->get_parent()); statementList.push_back(decl); removeList.push_back(decl); } // Traversal with Memory Pool to search for arrayType arrayTypeTraversal translateArrayType; traverseMemoryPoolVisitorPattern(translateArrayType); for(vector<SgArrayType*>::iterator i=arrayTypeList.begin(); i!=arrayTypeList.end(); ++i) { if(isLinearlizeArray) { linearizeArrayDeclaration(*i); } else { translateArrayDeclaration(*i); } } // Traversal with Memory Pool to search for pntrArrRefExp pntrArrRefTraversal translatePntrArrRefExp; traverseMemoryPoolVisitorPattern(translatePntrArrRefExp); for(vector<SgPntrArrRefExp*>::iterator i=pntrArrRefList.begin(); i!=pntrArrRefList.end(); ++i) { if(isLinearlizeArray) { linearizeArraySubscript(*i); } else { translateArraySubscript(*i); } } Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); for (Rose_STL_Container<SgNode*>::iterator i = functionList.begin(); i != functionList.end(); i++) { if((isSgProcedureHeaderStatement(*i) != NULL) || (isSgProgramHeaderStatement(*i) != NULL)){ SgFunctionDeclaration* functionBody = isSgFunctionDeclaration(*i); bool hasReturnVal = false; if(isSgProcedureHeaderStatement(functionBody)) { hasReturnVal = isSgProcedureHeaderStatement(functionBody)->isFunction(); } fixFortranSymbolTable(functionBody->get_definition(),hasReturnVal); } } // Traversal with Memory Pool to search for equivalenceStatement equivalencelTraversal translateEquivalenceStmt; traverseMemoryPoolVisitorPattern(translateEquivalenceStmt); for(vector<SgEquivalenceStatement*>::iterator i=equivalenceList.begin(); i!=equivalenceList.end(); ++i) { SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(*i); ROSE_ASSERT(equivalenceStatement); translateEquivalenceStatement(equivalenceStatement); statementList.push_back(equivalenceStatement); removeList.push_back(equivalenceStatement); } // Simple traversal, bottom-up, to translate the rest f2cTraversal f2c; f2c.traverseInputFiles(project,postorder); // removing all the unsed statement from AST for(vector<SgStatement*>::iterator i=statementList.begin(); i!=statementList.end(); ++i) { removeStatement(*i); (*i)->set_parent(NULL); } // deepDelete the removed nodes for(vector<SgNode*>::iterator i=removeList.begin(); i!=removeList.end(); ++i) { deepDelete(*i); } /* 1. There should be no Fortran-specific AST nodes in the whole AST graph after the translation. TODO: make sure translator generating clean AST */ //generateDOT(*project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000); return backend(project); }
bool TaintAnalysis::transfer(const Function& func, const DataflowNode& node_, NodeState& state, const std::vector<Lattice*>& dfInfo) { static size_t ncalls = 0; if (debug) { *debug <<"TaintAnalysis::transfer-" <<++ncalls <<"(func=" <<func.get_name() <<",\n" <<" node={" <<StringUtility::makeOneLine(node_.toString()) <<"},\n" <<" state={" <<state.str(this, " ") <<",\n" <<" dfInfo[" <<dfInfo.size() <<"]={...})\n"; } SgNode *node = node_.getNode(); assert(!dfInfo.empty()); FiniteVarsExprsProductLattice *prodLat = dynamic_cast<FiniteVarsExprsProductLattice*>(dfInfo.front()); bool modified = magic_tainted(node, prodLat); // some values are automatically tainted based on their name // Process AST nodes that transfer taintedness. Most of these operations have one or more inputs from which a result // is always calculated the same way. So we just gather up the inputs and do the calculation at the very end of this // function. The other operations are handled individually within their "if" bodies. TaintLattice *result = NULL; // result pointer into the taint lattice std::vector<TaintLattice*> inputs; // input pointers into the taint lattice if (isSgAssignInitializer(node)) { // as in "int a = b" SgAssignInitializer *xop = isSgAssignInitializer(node); TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(SgExpr2Var(xop->get_operand()))); inputs.push_back(in1); } else if (isSgAggregateInitializer(node)) { // as in "int a[1] = {b}" SgAggregateInitializer *xop = isSgAggregateInitializer(node); const SgExpressionPtrList &exprs = xop->get_initializers()->get_expressions(); for (size_t i=0; i<exprs.size(); ++i) { varID in_id = SgExpr2Var(exprs[i]); TaintLattice *in = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in_id)); inputs.push_back(in); } } else if (isSgInitializedName(node)) { SgInitializedName *xop = isSgInitializedName(node); if (xop->get_initializer()) { varID in1_id = SgExpr2Var(xop->get_initializer()); TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id)); inputs.push_back(in1); } } else if (isSgValueExp(node)) { // numeric and character constants SgValueExp *xop = isSgValueExp(node); result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(SgExpr2Var(xop))); if (result) modified = result->set_vertex(TaintLattice::VERTEX_UNTAINTED); } else if (isSgAddressOfOp(node)) { // as in "&x". The result taintedness has nothing to do with the value in x. /*void*/ } else if (isSgBinaryOp(node)) { // as in "a + b" SgBinaryOp *xop = isSgBinaryOp(node); varID in1_id = SgExpr2Var(isSgExpression(xop->get_lhs_operand())); TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id)); inputs.push_back(in1); varID in2_id = SgExpr2Var(isSgExpression(xop->get_rhs_operand())); TaintLattice *in2 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in2_id)); inputs.push_back(in2); if (isSgAssignOp(node)) { // copy the rhs lattice to the lhs lattice (as well as the entire '=' expression result) assert(in1 && in2); modified = in1->meetUpdate(in2); } } else if (isSgUnaryOp(node)) { // as in "-a" SgUnaryOp *xop = isSgUnaryOp(node); varID in1_id = SgExpr2Var(xop->get_operand()); TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id)); inputs.push_back(in1); } else if (isSgReturnStmt(node)) { // as in "return a". The result will always be dead, so we're just doing this to get some debugging output. Most // of our test inputs are functions, and the test examines the function's returned taintedness. SgReturnStmt *xop = isSgReturnStmt(node); varID in1_id = SgExpr2Var(xop->get_expression()); TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id)); inputs.push_back(in1); } // Update the result lattice (unless dead) with the inputs (unless dead) by using the meedUpdate() method. All this // means is that the new result will be the maximum of the old result and all inputs, where "maximum" is defined such // that "tainted" is greater than "untainted" (and both of them are greater than bottom/unknown). for (size_t i=0; i<inputs.size(); ++i) if (debug) *debug <<"TaintAnalysis::transfer: input " <<(i+1) <<" is " <<lattice_info(inputs[i]) <<"\n"; if (!result && varID::isValidVarExp(node)) { varID result_id(node); // NOTE: constructor doesn't handle all SgExpression nodes, thus the next "if" result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(result_id)); } if (!result && isSgExpression(node)) { varID result_id = SgExpr2Var(isSgExpression(node)); result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(result_id)); } if (result) { for (size_t i=0; i<inputs.size(); ++i) { if (inputs[i]) modified = result->meetUpdate(inputs[i]) || modified; } } if (debug) *debug <<"TaintAnalysis::transfer: result is " <<lattice_info(result) <<(modified?" (modified)":" (not modified)") <<"\n"; return modified; }
/** * \brief Return true if methodDecl overrides virtualMethodDecl. * \param methodDecl a method declaration. * \param virtualMethodDecl a method declaration. * \return Returns true if virtualMethodDecl is declared as a virtual * method and methodDecl has the same type signature and name * as virtualMethodDecl. * * NB: It is assumed that the class defining virtualMethodDecl is a base * class of the class defining methodDecl. */ bool methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, SgMemberFunctionDeclaration *virtualMethodDecl) { if ( !isVirtual(virtualMethodDecl) ) return false; // std::cout << "looks virtual" << std::endl; #if 0 // Hmmm ... couldn't we just compare mangled names? // No, we can't because this includes the scope info, which will // differ between classes. std::cout << "methodDecl: " << methodDecl->get_mangled_name().str() << std::endl; std::cout << "virtualMethodDecl: " << virtualMethodDecl->get_mangled_name().str() << std::endl; return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() ); #else if ( methodDecl->get_name() != virtualMethodDecl->get_name() ) return false; SgType *methodReturnType = methodDecl->get_orig_return_type(); SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type(); if ( methodReturnType != virtualMethodReturnType ) return false; int numMethodParams = 0; int numVirtualMethodParams = 0; SgFunctionParameterList *methodParameterList = methodDecl->get_parameterList(); if (methodParameterList != NULL) { numMethodParams = methodParameterList->get_args().size(); } SgFunctionParameterList *virtualMethodParameterList = virtualMethodDecl->get_parameterList(); if (virtualMethodParameterList != NULL) { numVirtualMethodParams = virtualMethodParameterList->get_args().size(); } if ( numMethodParams != numVirtualMethodParams ) return false; if ( numMethodParams == 0 ) return true; const SgInitializedNamePtrList &methodFormalParams = methodParameterList->get_args(); const SgInitializedNamePtrList &virtualMethodFormalParams = virtualMethodParameterList->get_args(); SgInitializedNamePtrList::const_iterator methodIt; SgInitializedNamePtrList::const_iterator virtualMethodIt; for(methodIt = methodFormalParams.begin(), virtualMethodIt = virtualMethodFormalParams.begin(); methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { SgInitializedName* methodFormalParam = *methodIt; ROSE_ASSERT(methodFormalParam != NULL); SgInitializedName* virtualMethodFormalParam = *virtualMethodIt; ROSE_ASSERT(virtualMethodFormalParam != NULL); if ( methodFormalParam->get_type() != virtualMethodFormalParam->get_type() ) return false; } return true; #endif }
void ControlDependenceGraph::_buildInterprocedural() { // Go through the SGNODE dependence nodes and create the appropriate // call site nodes, entry nodes etc. SgFunctionDefinition *func = isSgFunctionDefinition(_head); ROSE_ASSERT(func != NULL); // First create the entry node for the procedure _interprocedural->procedureEntry.entry = new DependenceNode(DependenceNode::ENTRY, func->get_declaration()); DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry); // Link the entry node up with all the nodes in the CDG which do not have // predecessors for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++) { DependenceNode *node = dynamic_cast < DependenceNode * >(*i); if ((node->numPredecessors() == 0) && (node != entry)) { establishEdge(entry, node); } } // create a formal out return argument, control dependent on the entry // node string return_name = func->get_declaration()->get_name().str(); return_name = return_name + " return"; _interprocedural->procedureEntry.formal_return = new DependenceNode(DependenceNode::FORMALOUT, return_name); DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return); establishEdge(entry, formal_return); // for each of the arguments in the function parameter list, add a // formal-in and formal-out node SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList(); SgInitializedNamePtrList params = paramlist->get_args(); for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++) { SgInitializedName *name = *i; DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN, name->get_name().str()); DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT, name->get_name().str()); establishEdge(entry, createNode(formal_in)); establishEdge(entry, createNode(formal_out)); _interprocedural->procedureEntry.formal_in[name] = formal_in; _interprocedural->procedureEntry.formal_out[name] = formal_out; // To preserve the order of arguments, we insert them into arg_order _interprocedural->procedureEntry.arg_order.push_back(name); } // Now we go through each of the SgNodes in our CDG. If any of them // contain a function call, we want to build a call site node for them. map < SgNode *, DependenceNode * >::iterator sgnode_iterator; for (sgnode_iterator = _sgnode_map.begin(); sgnode_iterator != _sgnode_map.end(); sgnode_iterator++) { SgNode *currnode = sgnode_iterator->first; list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode); if (calls.empty()) continue; for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++) { SgFunctionCallExp *call = *i; // This needs to be replaced with some call graph analysis SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function()); ROSE_ASSERT(func != NULL); SgName func_name = func->get_symbol()->get_name(); InterproceduralInfo::CallSiteStructure callstructure; callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call); // the call site is control dependent on the statement (i.e. for // the call site to happen, the statement must be executed) DependenceNode *callsite = createNode(callstructure.callsite); // addLink(callsite, getNode(currnode)); establishEdge(getNode(currnode), callsite); // create an actual out node for the return value, control // dependent on callsite string return_name = func_name.str(); return_name = return_name + " return"; callstructure.actual_return = new DependenceNode(DependenceNode::ACTUALOUT, return_name); DependenceNode *actual_return = createNode(callstructure.actual_return); establishEdge(callsite, actual_return); // For each argument in the function call, build an actual_in and // actual_out, control dependent on callsite SgExpressionPtrList args = call->get_args()->get_expressions(); for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++) { SgExpression *arg = *j; DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg); DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg); establishEdge(callsite, createNode(actual_in)); establishEdge(callsite, createNode(actual_out)); callstructure.actual_in[arg] = actual_in; callstructure.actual_out[arg] = actual_out; // To preserve the order of expressions in the parameter list, // // we insert them into expr_order callstructure.expr_order.push_back(arg); } // add the callstructure to interprocedural info _interprocedural->callsite_map[call] = callstructure; } } }
virtual void visit(SgNode* n) { if (isSgVarRefExp(n)) { SgVarRefExp* copy_vr = isSgVarRefExp(n); assert (copy_vr->get_symbol()); SgInitializedName* copy = copy_vr->get_symbol()->get_declaration(); assert (copy); SgInitializer* copyinit = copy->get_initializer(); SgScopeStatement* copyscope = SageInterface::getScope(copy->get_parent()->get_parent()); if (isSgAssignInitializer(copyinit)) { SgAssignInitializer* init = isSgAssignInitializer(copyinit); SgExpression* orig_expr = init->get_operand(); // cout << "orig is " << orig_expr->unparseToString() << ", copy is " << copy->get_name().str() << endl; if (!isPotentiallyModified(copy_vr, copyscope) && !isSgGlobal(copyscope) && !isSgNamespaceDefinitionStatement(copyscope)) { bool shouldReplace = false; if (isSgVarRefExp(orig_expr)) { SgVarRefExp* orig_vr = isSgVarRefExp(orig_expr); // cout << "Found potential copy from " << orig_vr->get_symbol()->get_name().str() << " to " << copy_vr->get_symbol()->get_name().str() << endl; SgInitializedName* orig = orig_vr->get_symbol()->get_declaration(); assert (orig); SgNode* origscope = orig->get_parent()->get_parent(); assert (origscope); if (!hasAddressTaken(orig_vr, origscope) && isSgBasicBlock(copyscope) && !isPotentiallyModifiedDuringLifeOf(isSgBasicBlock(copyscope), orig, copy) && !isSgGlobal(origscope) && !isSgNamespaceDefinitionStatement(origscope)) { shouldReplace = true; } } else if (isSgValueExp(orig_expr)) { shouldReplace = true; } // cout << "shouldReplace is " << shouldReplace << endl; if (shouldReplace) { assert (orig_expr); SgExpression* orig_copy = isSgExpression(orig_expr /*->copy(SgTreeCopy()) */); assert (orig_copy); orig_copy->set_parent(copy_vr->get_parent()); orig_copy->set_lvalue(copy_vr->get_lvalue()); ROSE_ASSERT(copy_vr != NULL); ROSE_ASSERT(copy_vr->get_parent() != NULL); // ROSE_ASSERT(isSgExpression(copy_vr->get_parent()) != NULL); // DQ (12/15/2006): Need to handle cases where the parent is a SgStatement or a SgExpression (or make it an error). // isSgExpression(copy_vr->get_parent())->replace_expression(copy_vr, orig_copy); SgStatement* statement = isSgStatement(copy_vr->get_parent()); if (statement != NULL) { statement->replace_expression(copy_vr, orig_copy); } else { SgExpression* expression = isSgExpression(copy_vr->get_parent()); if (expression != NULL) { expression->replace_expression(copy_vr, orig_copy); } else { printf ("Error: what is this copy_vr->get_parent() = %s \n",copy_vr->get_parent()->class_name().c_str()); ROSE_ASSERT(false); } } } } } } }
set<SgInitializedName*> computeLiveVars(SgStatement* stmt, const X86CTranslationPolicy& conv, map<SgLabelStatement*, set<SgInitializedName*> >& liveVarsForLabels, set<SgInitializedName*> currentLiveVars, bool actuallyRemove) { switch (stmt->variantT()) { case V_SgBasicBlock: { const SgStatementPtrList& stmts = isSgBasicBlock(stmt)->get_statements(); for (size_t i = stmts.size(); i > 0; --i) { currentLiveVars = computeLiveVars(stmts[i - 1], conv, liveVarsForLabels, currentLiveVars, actuallyRemove); } return currentLiveVars; } case V_SgPragmaDeclaration: return currentLiveVars; case V_SgDefaultOptionStmt: return currentLiveVars; case V_SgCaseOptionStmt: { return computeLiveVars(isSgCaseOptionStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove); } case V_SgLabelStatement: { liveVarsForLabels[isSgLabelStatement(stmt)] = currentLiveVars; return currentLiveVars; } case V_SgGotoStatement: { return liveVarsForLabels[isSgGotoStatement(stmt)->get_label()]; } case V_SgSwitchStatement: { SgSwitchStatement* s = isSgSwitchStatement(stmt); SgBasicBlock* swBody = isSgBasicBlock(s->get_body()); ROSE_ASSERT (swBody); const SgStatementPtrList& bodyStmts = swBody->get_statements(); set<SgInitializedName*> liveForBody; // Assumes any statement in the body is possible for (size_t i = 0; i < bodyStmts.size(); ++i) { setUnionInplace(liveForBody, computeLiveVars(bodyStmts[i], conv, liveVarsForLabels, currentLiveVars, actuallyRemove)); } return computeLiveVars(s->get_item_selector(), conv, liveVarsForLabels, liveForBody, actuallyRemove); } case V_SgContinueStmt: { return makeAllPossibleVars(conv); } case V_SgIfStmt: { set<SgInitializedName*> liveForBranches = computeLiveVars(isSgIfStmt(stmt)->get_true_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove); setUnionInplace(liveForBranches, (isSgIfStmt(stmt)->get_false_body() != NULL ? computeLiveVars(isSgIfStmt(stmt)->get_false_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove) : set<SgInitializedName*>())); return computeLiveVars(isSgIfStmt(stmt)->get_conditional(), conv, liveVarsForLabels, liveForBranches, actuallyRemove); } case V_SgWhileStmt: { while (true) { set<SgInitializedName*> liveVarsSave = currentLiveVars; currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, false); currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_condition(), conv, liveVarsForLabels, currentLiveVars, false); setUnionInplace(currentLiveVars, liveVarsSave); if (liveVarsSave == currentLiveVars) break; } if (actuallyRemove) { set<SgInitializedName*> liveVarsSave = currentLiveVars; currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, true); currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_condition(), conv, liveVarsForLabels, currentLiveVars, true); setUnionInplace(currentLiveVars, liveVarsSave); } return currentLiveVars; } case V_SgBreakStmt: return set<SgInitializedName*>(); case V_SgExprStatement: { SgExpression* e = isSgExprStatement(stmt)->get_expression(); switch (e->variantT()) { case V_SgAssignOp: { SgVarRefExp* lhs = isSgVarRefExp(isSgAssignOp(e)->get_lhs_operand()); ROSE_ASSERT (lhs); SgInitializedName* in = lhs->get_symbol()->get_declaration(); if (currentLiveVars.find(in) == currentLiveVars.end()) { if (actuallyRemove) { // cerr << "Removing assignment " << e->unparseToString() << endl; isSgStatement(stmt->get_parent())->remove_statement(stmt); } return currentLiveVars; } else { currentLiveVars.erase(in); getUsedVariables(isSgAssignOp(e)->get_rhs_operand(), currentLiveVars); return currentLiveVars; } } case V_SgFunctionCallExp: { getUsedVariables(e, currentLiveVars); SgFunctionRefExp* fr = isSgFunctionRefExp(isSgFunctionCallExp(e)->get_function()); ROSE_ASSERT (fr); if (fr->get_symbol()->get_declaration() == conv.interruptSym->get_declaration()) { setUnionInplace(currentLiveVars, makeAllPossibleVars(conv)); return currentLiveVars; } else { return currentLiveVars; } } default: { getUsedVariables(e, currentLiveVars); return currentLiveVars; } } } case V_SgVariableDeclaration: { ROSE_ASSERT (isSgVariableDeclaration(stmt)->get_variables().size() == 1); SgInitializedName* in = isSgVariableDeclaration(stmt)->get_variables()[0]; bool isConst = isConstType(in->get_type()); if (currentLiveVars.find(in) == currentLiveVars.end() && isConst) { if (actuallyRemove) { // cerr << "Removing decl " << stmt->unparseToString() << endl; isSgStatement(stmt->get_parent())->remove_statement(stmt); } return currentLiveVars; } else { currentLiveVars.erase(in); if (in->get_initializer()) { getUsedVariables(in->get_initializer(), currentLiveVars); } return currentLiveVars; } } default: cerr << "computeLiveVars: " << stmt->class_name() << endl; abort(); } }
void TransformationSupport::getTransformationOptions ( SgNode* astNode, list<OptionDeclaration> & generatedList, string identifingTypeName ) { // This function searches for variables of type ScopeBasedTransformationOptimization. Variables // of type ScopeBasedTransformationOptimization are used to communicate optimizations from the // application to the preprocessor. If called from a project or file object it traverses down to // the global scope of the file and searches only the global scope, if called from and other // location within the AST it searches the current scope and then traverses the parent nodes to // find all enclosing scopes until in reaches the global scope. At each scope it searches for // variables of type ScopeBasedTransformationOptimization. // printf ("######################### START OF TRANSFORMATION OPTION QUERY ######################## \n"); ROSE_ASSERT (astNode != NULL); ROSE_ASSERT (identifingTypeName.c_str() != NULL); #if 0 printf ("In getTransformationOptions(): astNode->sage_class_name() = %s generatedList.size() = %d \n", astNode->sage_class_name(),generatedList.size()); SgLocatedNode* locatedNode = isSgLocatedNode(astNode); if (locatedNode != NULL) { printf (" locatedNode->get_file_info()->get_filename() = %s \n",locatedNode->get_file_info()->get_filename()); printf (" locatedNode->get_file_info()->get_line() = %d \n",locatedNode->get_file_info()->get_line()); } #endif switch (astNode->variant()) { case ProjectTag: { SgProject* project = isSgProject(astNode); ROSE_ASSERT (project != NULL); //! Loop through all the files in the project and call the mainTransform function for each file int i = 0; for (i=0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); // printf ("Calling Query::traverse(SgFile,QueryFunctionType,QueryAssemblyFunctionType) \n"); getTransformationOptions ( file, generatedList, identifingTypeName ); } break; } case SourceFileTag: { SgSourceFile* file = isSgSourceFile(astNode); ROSE_ASSERT (file != NULL); SgGlobal* globalScope = file->get_globalScope(); ROSE_ASSERT (globalScope != NULL); ROSE_ASSERT (isSgGlobal(globalScope) != NULL); getTransformationOptions ( globalScope, generatedList, identifingTypeName ); break; } // Global Scope case GLOBAL_STMT: { SgGlobal* globalScope = isSgGlobal(astNode); ROSE_ASSERT (globalScope != NULL); SgSymbolTable* symbolTable = globalScope->get_symbol_table(); ROSE_ASSERT (symbolTable != NULL); getTransformationOptions ( symbolTable, generatedList, identifingTypeName ); // printf ("Processed global scope, exiting .. \n"); // ROSE_ABORT(); break; } case SymbolTableTag: { // List the variable in each scope // printf ("List all the variables in this symbol table! \n"); SgSymbolTable* symbolTable = isSgSymbolTable(astNode); ROSE_ASSERT (symbolTable != NULL); bool foundTransformationOptimizationSpecifier = false; // printf ("Now print out the information in the symbol table for this scope: \n"); // symbolTable->print(); #if 0 // I don't know when a SymbolTable is given a name! printf ("SymbolTable has a name = %s \n", (symbolTable->get_no_name()) ? "NO: it has no name" : "YES: it does have a name"); if (!symbolTable->get_no_name()) printf ("SymbolTable name = %s \n",symbolTable->get_name().str()); else ROSE_ASSERT (symbolTable->get_name().str() == NULL); #endif if (symbolTable->get_table() != NULL) { SgSymbolTable::hash_iterator i = symbolTable->get_table()->begin(); int counter = 0; while (i != symbolTable->get_table()->end()) { ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL ); // printf ("Initial info: number: %d pair.first (SgName) = %s pair.second (SgSymbol) sage_class_name() = %s \n", // counter,(*i).first.str(),(*i).second->sage_class_name()); SgSymbol* symbol = isSgSymbol((*i).second); ROSE_ASSERT ( symbol != NULL ); SgType* type = symbol->get_type(); ROSE_ASSERT ( type != NULL ); SgNamedType* namedType = isSgNamedType(type); string typeName; if (namedType != NULL) { SgName n = namedType->get_name(); typeName = namedType->get_name().str(); // char* nameString = namedType->get_name().str(); // printf ("Type is: (named type) = %s \n",nameString); ROSE_ASSERT (identifingTypeName.c_str() != NULL); // ROSE_ASSERT (typeName != NULL); // printf ("In getTransformationOptions(): typeName = %s identifingTypeName = %s \n",typeName.c_str(),identifingTypeName.c_str()); // if ( (typeName != NULL) && ( typeName == identifingTypeName) ) if ( typeName == identifingTypeName ) { // Now look at the parameter list to the constructor and save the // values into the list. // printf ("Now save the constructor arguments! \n"); SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol); if ( variableSymbol != NULL ) { SgInitializedName* initializedNameDeclaration = variableSymbol->get_declaration(); ROSE_ASSERT (initializedNameDeclaration != NULL); SgDeclarationStatement* declarationStatement = initializedNameDeclaration->get_declaration(); ROSE_ASSERT (declarationStatement != NULL); SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declarationStatement); ROSE_ASSERT (variableDeclaration != NULL); getTransformationOptionsFromVariableDeclarationConstructorArguments(variableDeclaration,generatedList); foundTransformationOptimizationSpecifier = true; // printf ("Exiting after saving the constructor arguments! \n"); // ROSE_ABORT(); } else { #if 0 printf ("Not a SgVariableSymbol: symbol->sage_class_name() = %s \n", symbol->sage_class_name()); #endif } } else { #if 0 printf ("typeName != identifingTypeName : symbol->sage_class_name() = %s \n", symbol->sage_class_name()); #endif #if 0 // I don't think this should ever be NULL (but it is sometimes) if (typeName != NULL) printf ("typeName == NULL \n"); #endif } } else { typeName = (char *)type->sage_class_name(); } // printf ("In while loop at the base: counter = %d \n",counter); i++; counter++; } } else { // printf ("Pointer to symbol table is NULL \n"); } // printf ("foundTransformationOptimizationSpecifier = %s \n",foundTransformationOptimizationSpecifier ? "true" : "false"); // SgSymbolTable objects don't have a parent node (specifically they lack a get_parent // member function in the interface)! break; } case BASIC_BLOCK_STMT: { // List the variable in each scope // printf ("List all the variables in this scope! \n"); SgBasicBlock* basicBlock = isSgBasicBlock(astNode); ROSE_ASSERT (basicBlock != NULL); SgSymbolTable* symbolTable = basicBlock->get_symbol_table(); ROSE_ASSERT (symbolTable != NULL); getTransformationOptions ( symbolTable, generatedList, identifingTypeName ); // Next go (fall through this case) to the default case so that we traverse the parent // of the SgBasicBlock. // break; } default: // Most cases will be the default (this is by design) // printf ("default in switch found in globalQueryGetListOperandStringFunction() (sage_class_name = %s) \n",astNode->sage_class_name()); // Need to recursively backtrack through the parents until we reach the SgGlobal (global scope) SgStatement* statement = isSgStatement(astNode); if (statement != NULL) { SgNode* parentNode = statement->get_parent(); ROSE_ASSERT (parentNode != NULL); // printf ("parent = %p parentNode->sage_class_name() = %s \n",parentNode,parentNode->sage_class_name()); SgStatement* parentStatement = isSgStatement(parentNode); if (parentStatement == NULL) { printf ("parentStatement == NULL: statement (%p) is a %s \n",statement,statement->sage_class_name()); printf ("parentStatement == NULL: statement->get_file_info()->get_filename() = %s \n",statement->get_file_info()->get_filename()); printf ("parentStatement == NULL: statement->get_file_info()->get_line() = %d \n",statement->get_file_info()->get_line()); } ROSE_ASSERT (parentStatement != NULL); // Call this function recursively (directly rather than through the query mechanism) getTransformationOptions ( parentStatement, generatedList, identifingTypeName ); } else { // printf ("astNode is not a SgStatement! \n"); } break; } #if 0 printf ("At BASE of getTransformationOptions(): astNode->sage_class_name() = %s size of generatedList = %d \n", astNode->sage_class_name(),generatedList.size()); #endif // printf ("######################### END OF TRANSFORMATION OPTION QUERY ######################## \n"); }
void RewriteFSM::visitSgFunctionDeclaration(SgFunctionDeclaration *FD) { SgFunctionDefinition *fdef = FD->get_definition(); if (!fdef) { return; } if (debugHooks) { std::cout << "Func decl: " << FD << " " << FD->get_name() << std::endl; } std::string modName = FD->get_name().getString(); HtdInfoAttribute *htd = getHtdInfoAttribute(fdef); bool isStreamingStencil = false; size_t pos = 0; if ((pos = modName.find(StencilStreamPrefix)) != std::string::npos && pos == 0) { isStreamingStencil = true; } #define hostEntryPrefix "__HTC_HOST_ENTRY_" bool isHostEntry = false; if ((pos = modName.find(hostEntryPrefix)) != std::string::npos && pos == 0) { isHostEntry = true; } // Emit a default, unnamed thread group. std::string modWidth = boost::to_upper_copy(modName) + "_HTID_W"; if (isStreamingStencil) { // The streaming version of a stencil must have width 0. htd->appendDefine(modWidth, "0"); } else if (isHostEntry) { htd->appendDefine(modWidth, "1"); } else if (htd->moduleWidth != -1) { htd->appendDefine(modWidth, boost::lexical_cast<std::string>(htd->moduleWidth)); } else { DefaultModuleWidthAttribute *dwAttr = getDefaultModuleWidthAttribute(SageInterface::getGlobalScope(fdef)); if (dwAttr) { htd->appendDefine(modWidth, boost::lexical_cast<std::string>(dwAttr->width)); } else { htd->appendDefine(modWidth, "5"); } } htd->appendModule(modName, "", modWidth); // For streaming stencils, ProcessStencils inserts a canned sequence, // so we bypass generating a normal FSM. if (isStreamingStencil) { return; } // // Create new case body blocks for each state. // The first executable statement starts the first state, and each // label starts a new state. // std::map<SgLabelStatement *, int> labelToState; std::map<int, std::string> stateToName; SgBasicBlock *funcBody = isSgBasicBlock(fdef->get_body()); SgStatementPtrList &stmts = funcBody->get_statements(); std::vector<SgStatement *>::iterator SI, SP; for (SI = stmts.begin(); SI != stmts.end(); ++SI) { if (!isSgDeclarationStatement(*SI)) { break; } } if (SI == stmts.end()) { return; } SP = SI; std::vector<SgBasicBlock *> newBlocks; SgBasicBlock *newbb = SageBuilder::buildBasicBlock(); newBlocks.push_back(newbb); stateToName[1] = "__START"; bool prevIsLabel = false; for (; SI != stmts.end(); ++SI) { SgStatement *stmt = *SI; SgLabelStatement *labstmt = isSgLabelStatement(stmt); if (labstmt) { if (!prevIsLabel) { newbb = SageBuilder::buildBasicBlock(); newBlocks.push_back(newbb); } int snum = newBlocks.size(); labelToState[labstmt] = snum; stateToName[snum] += "__" + labstmt->get_label().getString(); prevIsLabel = true; #if 1 // TODO: these labels can carry preproc infos-- but the unparser // doesn't output them if the label is not actually output. AttachedPreprocessingInfoType *comments = labstmt->getAttachedPreprocessingInfo(); if (comments && comments->size() > 0) { std::cerr << "DEVWARN: losing Preprocinfo on label" << std::endl; SageInterface::dumpPreprocInfo(labstmt); } #endif stmt->unsetOutputInCodeGeneration(); SageInterface::appendStatement(stmt, newbb); } else { prevIsLabel = false; SageInterface::appendStatement(stmt, newbb); } } stmts.erase(SP, stmts.end()); // Add module name to each state name and create enum decl. SgEnumDeclaration *enumDecl = SageBuilder::buildEnumDeclaration("states", fdef); for (int i = 1; i <= newBlocks.size(); i++) { stateToName[i] = modName + stateToName[i]; boost::to_upper(stateToName[i]); SgName nm(stateToName[i]); SgInitializedName *enumerator = SageBuilder::buildInitializedName(nm, SageBuilder::buildIntType(), SageBuilder::buildAssignInitializer(SageBuilder::buildIntVal(i))); enumerator->set_scope(funcBody); enumDecl->append_enumerator(enumerator); // Add the instruction to the htd info. htd->appendInst(nm.getString()); } SageInterface::prependStatement(enumDecl, funcBody); if (!debugHooks) { enumDecl->unsetOutputInCodeGeneration(); } SgGlobal *GS = SageInterface::getGlobalScope(FD); SgVariableDeclaration *declHtValid = HtDeclMgr::buildHtlVarDecl("PR_htValid", GS); SgVariableDeclaration *declHtInst = HtDeclMgr::buildHtlVarDecl("PR_htInst", GS); SgFunctionDeclaration *declHtContinue = HtDeclMgr::buildHtlFuncDecl("HtContinue", GS); SgFunctionDeclaration *declHtAssert = HtDeclMgr::buildHtlFuncDecl("HtAssert", GS); // // Create the finite state machine switch statement "switch (PR_htInst)", // and insert guard "if (PR_htValid)". // SgBasicBlock *newSwitchBody = SageBuilder::buildBasicBlock(); SgExpression *htInstExpr = SageBuilder::buildVarRefExp(declHtInst); SgSwitchStatement *newSwitch = SageBuilder::buildSwitchStatement(htInstExpr, newSwitchBody); SgExpression *htValidExpr = SageBuilder::buildVarRefExp(declHtValid); SgIfStmt *newIfStmt = SageBuilder::buildIfStmt(htValidExpr, SageBuilder::buildBasicBlock(newSwitch), 0); SageInterface::appendStatement(newIfStmt, funcBody); int casenum = 1; foreach (SgBasicBlock *newCaseBody, newBlocks) { SgExpression *caseExpr = SageBuilder::buildEnumVal_nfi(casenum, enumDecl, stateToName[casenum]); SgCaseOptionStmt *newCase = SageBuilder::buildCaseOptionStmt(caseExpr, newCaseBody); SageInterface::appendStatement(newCase, newSwitchBody); casenum++; }
Detection_InheritedAttribute DetectionTraversal::evaluateInheritedAttribute (SgNode* astNode, Detection_InheritedAttribute inheritedAttribute ) { #if 0 printf ("In DetectionTraversal::evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif // DQ (2/3/2016): Recognize IR nodes that are representative of target DSL abstractions. bool foundTargetDslAbstraction = DSL_Support::isDslAbstraction(astNode); #if 1 printf ("In DetectionTraversal::evaluateInheritedAttribute(): astNode = %p = %s: foundTargetDslAbstraction = %s \n",astNode,astNode->class_name().c_str(),foundTargetDslAbstraction ? "true" : "false"); #endif #if 0 // OLD CODE (represented by DSL_Support::isDslAbstraction() function). // Detection of stencil declaration and stencil operator. // Where the stencil specification is using std::vectors as parameters to the constructor, we have to first // find the stencil declaration and read the associated SgVarRefExp to get the variable names used. // Then a finite state machine can be constructed for each of the input variables so that we can // interpret the state when the stencil operator is constructed. SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(astNode); if (variableDeclaration != NULL) { // Get the SgInitializedName from the SgVariableDeclaration. SgInitializedName* initializedName = SageInterface::getFirstInitializedName(variableDeclaration); SgType* base_type = initializedName->get_type()->findBaseType(); ROSE_ASSERT(base_type != NULL); // SgClassType* classType = isSgClassType(initializedName->get_type()); SgClassType* classType = isSgClassType(base_type); if (classType != NULL) { #if 1 printf ("In DetectionTraversal::evaluateInheritedAttribute(): case SgClassType: class name = %s \n",classType->get_name().str()); #endif // Check if this is associated with a template instantiation. SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classType->get_declaration()); if (templateInstantiationDecl != NULL) { #if 1 printf ("case SgTemplateInstaiationDecl: class name = %s \n",classType->get_name().str()); printf ("case SgTemplateInstaiationDecl: templateInstantiationDecl->get_templateName() = %s \n",templateInstantiationDecl->get_templateName().str()); #endif // inheritedAttribute.set_StencilDeclaration(templateInstantiationDecl->get_templateName() == "Stencil"); // inheritedAttribute.set_StencilOperatorDeclaration(templateInstantiationDecl->get_templateName() == "StencilOperator"); if (templateInstantiationDecl->get_templateName() == "Stencil") { // DQ (2/8/2015): Ignore compiler generated IR nodes (from template instantiations, etc.). // Note that simpleCNS.cpp generates one of these from it's use of the tuple template and associated template instantations. // DQ: Test the DSL support. ROSE_ASSERT(isMatchingClassType(classType,"Stencil",true) == true); checkAndResetToMakeConsistantCompilerGenerated(initializedName); if (initializedName->isCompilerGenerated() == false) { // Save the SgInitializedName associated with the stencil. // stencilInitializedNameList.push_back(initializedName); // inheritedAttribute.set_StencilDeclaration(true); // foundStencilVariable = true; #if 1 printf ("Detected Stencil<> typed variable: initializedName = %p name = %s \n",initializedName,initializedName->get_name().str()); // printf (" --- stencilInitializedNameList.size() = %zu \n",stencilInitializedNameList.size()); #endif #if 1 initializedName->get_file_info()->display("In DetectionTraversal::evaluateInheritedAttribute(): initializedName : debug"); #endif #if 0 Stencil_Attribute* dslAttribute = new Stencil_Attribute(); #if 1 printf ("Adding (Stencil) dslAttribute = %p \n",dslAttribute); #endif ROSE_ASSERT(dslAttribute != NULL); // virtual void addNewAttribute (std::string s, AstAttribute *a); initializedName->addNewAttribute(StencilVariable,dslAttribute); #endif } } } SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration()); if (classDeclaration != NULL) { if (classDeclaration->get_name() == "Point") { // Save the SgInitializedName associated with the Point type. #if 0 printf ("Detected Point<> typed variable: initializedName = %p name = %s \n",initializedName,initializedName->get_name().str()); #endif checkAndResetToMakeConsistantCompilerGenerated(initializedName); if (initializedName->isCompilerGenerated() == false) { // pointInitializedNameList.push_back(initializedName); #if 0 Point_Attribute* dslAttribute = new Point_Attribute(); printf ("Adding (Point) dslAttribute = %p \n",dslAttribute); ROSE_ASSERT(dslAttribute != NULL); // virtual void addNewAttribute (std::string s, AstAttribute *a); initializedName->addNewAttribute(PointVariable,dslAttribute); #endif } } } } } #endif #if 1 printf ("Leaving DetectionTraversal::evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif // Construct the return attribute from the modified input attribute. return Detection_InheritedAttribute(inheritedAttribute); }
int main(int argc, char **argv) { SgProject *project = frontend(argc, argv); // Instantiate a class hierarchy wrapper. ClassHierarchyWrapper classHierarchy( project ); #if 0 std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project, V_SgVariableDefinition); for (std::list<SgNode *>::iterator it = nodes2.begin(); it != nodes2.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDefinition *varDefn = isSgVariableDefinition(n); ROSE_ASSERT(varDefn != NULL); std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl; } std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project, V_SgVariableDeclaration); for (std::list<SgNode *>::iterator it = nodes1.begin(); it != nodes1.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDeclaration *varDecl = isSgVariableDeclaration(n); ROSE_ASSERT(varDecl != NULL); SgInitializedNamePtrList &variables = varDecl->get_variables(); SgInitializedNamePtrList::iterator varIter; for (varIter = variables.begin(); varIter != variables.end(); ++varIter) { SgNode *var = *varIter; ROSE_ASSERT(var != NULL); SgInitializedName *initName = isSgInitializedName(var); ROSE_ASSERT(initName != NULL); if ( isSgClassType(initName->get_type()) ) { SgClassType *classType = isSgClassType(initName->get_type()); ROSE_ASSERT(classType != NULL); SgDeclarationStatement *declStmt = classType->get_declaration(); ROSE_ASSERT(declStmt != NULL); SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt); ROSE_ASSERT(classDeclaration != NULL); // std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl; SgClassDefinition *classDefinition = classDeclaration->get_definition(); if ( classDefinition != NULL ) { std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl; } } } } std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDeclaration); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDeclaration *classDeclaration1 = isSgClassDeclaration(n); ROSE_ASSERT(classDeclaration1 != NULL); SgDeclarationStatement *definingDecl = classDeclaration1->get_definingDeclaration(); if ( definingDecl == NULL ) continue; SgClassDeclaration *classDeclaration = isSgClassDeclaration(definingDecl); ROSE_ASSERT(classDeclaration != NULL); SgClassDefinition *classDefinition = classDeclaration->get_definition(); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #endif #if 1 #if 0 std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDefinition); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDefinition *classDefinition = isSgClassDefinition(n); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #else // Collect all function/method invocations. std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgFunctionCallExp); unsigned int numCallSites = 0; unsigned int numMonomorphicCallSites = 0; unsigned int numPossibleResolutions = 0; // Visit each call site. for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(n); ROSE_ASSERT(functionCallExp != NULL); // We are only interested in examining method invocations. bool isDotExp = false; bool isLhsRefOrPtr = false; // std::cout << "method?: " << functionCallExp->unparseToCompleteString() << std::endl; if ( !isMethodCall(functionCallExp, isDotExp, isLhsRefOrPtr) ) continue; // std::cout << "method: " << functionCallExp->unparseToCompleteString() << std::endl; numCallSites++; if ( isDotExp && !isLhsRefOrPtr ) { // If this is a dot expression (i.e., a.foo()), we can // statically determine its type-- unless the left-hand // side is a reference type. numMonomorphicCallSites++; numPossibleResolutions++; // std::cout << "dot: " << functionCallExp->unparseToCompleteString() << std::endl; continue; } // std::cout << "methodPtr: " << functionCallExp->unparseToCompleteString() << std::endl; // Retrieve the static function declaration. SgFunctionDeclaration *functionDeclaration = getFunctionDeclaration(functionCallExp); // Ensure it is actually a method declaration. SgMemberFunctionDeclaration *memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration); ROSE_ASSERT(memberFunctionDeclaration != NULL); unsigned int numResolutionsForMethod = 0; // Certainly can be resolved to the static method (unless it // is pure virtual). if ( !isPureVirtual(memberFunctionDeclaration) ) { numResolutionsForMethod++; } #if 0 if ( ( isVirtual(functionDeclaration) ) || ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) { #else if ( isVirtual(functionDeclaration) ) { #endif // std::cout << "tracking: " << functionDeclaration->unparseToString() << std::endl; SgClassDefinition *classDefinition = isSgClassDefinition(memberFunctionDeclaration->get_scope()); ROSE_ASSERT(classDefinition != NULL); SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); // std::cout << "subclass" << std::endl; // Iterate over all of the methods defined in this subclass. SgDeclarationStatementPtrList &decls = subclass->get_members(); for (SgDeclarationStatementPtrList::iterator declIter = decls.begin(); declIter != decls.end(); ++declIter) { SgDeclarationStatement *declStmt = *declIter; ROSE_ASSERT(declStmt != NULL); SgMemberFunctionDeclaration *method = isSgMemberFunctionDeclaration(declStmt); if ( method == NULL ) { continue; } // std::cout << "checking overrides" << std::endl; // Determine whether subclass of the class defining this // method overrides the method. #if 1 if ( matchingFunctions(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; // Do not consider a pure virtual method to be an // overriding method (since it can not be invoked). if ( !isPureVirtual(method) ) { numResolutionsForMethod++; } } #else if ( methodOverridesVirtualMethod(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; numResolutionsForMethod++; } #endif } } if ( numResolutionsForMethod <= 1 ) numMonomorphicCallSites++; numPossibleResolutions += numResolutionsForMethod; if ( ( numResolutionsForMethod ) > 1 ) { std::cout << "Method invocation has " << numResolutionsForMethod << " possible resolutions " << std::endl; std::cout << functionCallExp->unparseToCompleteString() << std::endl; } } } #endif #endif return 0; }
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()); } } }
ExprSynAttr *examineVariableDeclaration(SgVariableDeclaration* decl, ostream &out) { SgInitializedNamePtrList& name_list = decl->get_variables(); SgInitializedNamePtrList::const_iterator name_iter; ExprSynAttr *ret = NULL; ExprSynAttr *gc = NULL; ret = new ExprSynAttr(); for (name_iter = name_list.begin(); name_iter != name_list.end(); name_iter++) { SgInitializedName* name = *name_iter; SgSymbol* symbol = name->get_symbol_from_symbol_table(); SgType *type = symbol->get_type(); int nr_stars = 0; stringstream ss1; while (isSgArrayType(type) || isSgPointerType(type)) { if (isSgArrayType(type)) { SgArrayType *atype = isSgArrayType(type); SgExpression *expr = atype->get_index(); type = atype->get_base_type(); ss1 << "["; if (expr) examineExpr(expr, ss1); ss1 << "]"; } else { SgPointerType *ttype = isSgPointerType(type); type = ttype->get_base_type(); nr_stars++; } } examinePrimTypeName(type, ret->code); ret->code << " "; for (int i = 0; i < nr_stars; ++i) ret->code << "*"; ret->code << symbol->get_name().getString(); ret->code << ss1.str(); ss1.str(""); SgInitializer *initer = name->get_initializer(); if (initer) { switch (initer->variantT()) { case V_SgAssignInitializer: SgAssignInitializer *ai = isSgAssignInitializer(initer); SgExpression *expr = ai->get_operand(); if (expr) { ret->code << "="; gc = examineExpr(expr, ret->code); if (gc != NULL) delete gc; } break; default: break; } } /* end of this decl */ ret->code << ";"; out << ret->code.str(); return ret; /* cout << "[Decl] Variable (name:"<<symbol->get_name().getString(); cout << ",type:"<<symbol->get_type()->class_name(); cout << ",init:"; SgInitializer* init_expr = name->get_initializer(); if (init_expr) cout << init_expr->class_name(); else cout << "none"; cout << ")" << endl; */ } }
void SgNode::insertSourceCode ( SgProject & project, const char* sourceCodeString, const char* localDeclaration, const char* globalDeclaration, bool locateNewCodeAtTop, bool isADeclaration ) { // If this function is useful only for SgBasicBlock then it should be put into that class directly. // This function is used to insert code into AST object for which insertion make sense: // (specifically any BASIC_BLOCK_STMT) if (variant() != BASIC_BLOCK_STMT) { printf ("ERROR: insert only make since for BASIC_BLOCK_STMT statements (variant() == variant()) \n"); ROSE_ABORT(); } SgBasicBlock* currentBlock = isSgBasicBlock(this); ROSE_ASSERT (currentBlock != NULL); // printf ("##### Calling SgNode::generateAST() \n"); #if 0 printf ("In insertSourceCode(): globalDeclaration = \n%s\n",globalDeclaration); printf ("In insertSourceCode(): localDeclaration = \n%s\n",localDeclaration); printf ("In insertSourceCode(): sourceCodeString = \n%s\n",sourceCodeString); #endif // SgNode* newTransformationAST = generateAST (project,sourceCodeString,globalDeclaration); // ROSE_ASSERT (newTransformationAST != NULL); SgStatementPtrList* newTransformationStatementListPtr = generateAST (project,sourceCodeString,localDeclaration,globalDeclaration,isADeclaration); ROSE_ASSERT (newTransformationStatementListPtr != NULL); ROSE_ASSERT (newTransformationStatementListPtr->size() > 0); // printf ("##### DONE: Calling SgNode::generateAST() \n"); // get a reference to the statement list out of the basic block SgStatementPtrList & currentStatementList = currentBlock->get_statements(); if (locateNewCodeAtTop == true) { // Insert at top of list (pull the elements off the bottom of the new statement list to get the order correct // printf ("Insert new statements (new statement list size = %d) at the top of the block (in reverse order to preset the order in the final block) \n",newTransformationStatementListPtr->size()); SgStatementPtrList::reverse_iterator transformationStatementIterator; for (transformationStatementIterator = newTransformationStatementListPtr->rbegin(); transformationStatementIterator != newTransformationStatementListPtr->rend(); transformationStatementIterator++) { // Modify where a statement is inserted to avoid dependent variables from being inserted // before they are declared. // Get a list of the variables // Generate the list of types used within the target subtree of the AST list<string> typeNameStringList = NameQuery::getTypeNamesQuery ( *transformationStatementIterator ); int statementCounter = 0; int previousStatementCounter = 0; // Declaration furthest in source sequence of all variables referenced in code to be inserted (last in source sequence order) // SgStatementPtrList::iterator furthestDeclarationInSourceSequence = NULL; SgStatementPtrList::iterator furthestDeclarationInSourceSequence; #if 0 string unparsedDeclarationCodeString = (*transformationStatementIterator)->unparseToString(); ROSE_ASSERT (unparsedDeclarationCodeString.c_str() != NULL); printf ("unparsedDeclarationCodeString = %s \n",unparsedDeclarationCodeString.c_str()); #endif if ( typeNameStringList.size() > 0 ) { // There should be at least one type in the statement ROSE_ASSERT (typeNameStringList.size() > 0); // printf ("typeNameStringList.size() = %d \n",typeNameStringList.size()); // printf ("This statement has a dependence upon a variable of some type \n"); // Loop over all the types and get list of variables of each type // (so they can be declared properly when the transformation is compiled) list<string>::iterator typeListStringElementIterator; for (typeListStringElementIterator = typeNameStringList.begin(); typeListStringElementIterator != typeNameStringList.end(); typeListStringElementIterator++) { // printf ("Type = %s \n",(*typeListStringElementIterator).c_str()); // Find a list of names of variable of type (*listStringElementIterator) list<string> operandNameStringList = NameQuery::getVariableNamesWithTypeNameQuery ( *transformationStatementIterator, *typeListStringElementIterator ); // There should be at least one variable of that type in the statement ROSE_ASSERT (operandNameStringList.size() > 0); // printf ("operandNameStringList.size() = %d \n",operandNameStringList.size()); // Loop over all the types and get list of variable of each type list<string>::iterator variableListStringElementIterator; for (variableListStringElementIterator = operandNameStringList.begin(); variableListStringElementIterator != operandNameStringList.end(); variableListStringElementIterator++) { #if 0 printf ("Type = %s Variable = %s \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif string variableName = *variableListStringElementIterator; string typeName = *typeListStringElementIterator; SgName name = variableName.c_str(); SgVariableSymbol* symbol = currentBlock->lookup_var_symbol(name); if ( symbol != NULL ) { // found a variable with name -- make sure that the declarations // represented by *transformationStatementIterator are inserted // after their declaration. #if 0 printf ("Found a valid symbol corresponding to Type = %s Variable = %s (must be defined in the local scope) \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif ROSE_ASSERT (symbol != NULL); SgInitializedName* declarationInitializedName = symbol->get_declaration(); ROSE_ASSERT (declarationInitializedName != NULL); SgDeclarationStatement* declarationStatement = declarationInitializedName->get_declaration(); ROSE_ASSERT (declarationStatement != NULL); #if 0 printf ("declarationStatementString located at line = %d of file = %s \n", rose::getLineNumber(declarationStatement), rose::getFileName(declarationStatement)); string declarationStatementString = declarationStatement->unparseToString(); printf ("declarationStatementString = %s \n",declarationStatementString.c_str()); #endif statementCounter = 1; SgStatementPtrList::iterator i = currentStatementList.begin(); bool declarationFound = false; while ( ( i != currentStatementList.end() ) && ( declarationFound == false ) ) { // searching for the declarationStatement #if 0 printf ("statementCounter = %d previousStatementCounter = %d \n", statementCounter,previousStatementCounter); string currentStatementString = (*i)->unparseToString(); printf ("currentStatementString = %s \n",currentStatementString.c_str()); #endif if ( (*i == declarationStatement) && (statementCounter > previousStatementCounter) ) { // printf ("Found the declarationStatement at position (statementCounter = %d previousStatementCounter = %d) \n",statementCounter,previousStatementCounter); declarationFound = true; } else { // printf ("Not the declaration we are looking for! \n"); i++; statementCounter++; } } // Save a reference to the variable declaration that is furthest in // the source sequence so that we can append the new statement just // after it (so that variables referenced in the new statement will // be defined). if ( (statementCounter > previousStatementCounter) && ( declarationFound == true ) ) { previousStatementCounter = statementCounter; furthestDeclarationInSourceSequence = i; } #if 0 printf ("AFTER LOOP OVER STATEMENTS: previousStatementCounter = %d \n",previousStatementCounter); string lastStatementString = (*furthestDeclarationInSourceSequence)->unparseToString(); printf ("lastStatementString = %s \n",lastStatementString.c_str()); #endif } else { // If the variable is not found then insert the new statement at the front of the list #if 0 printf ("Can NOT find a valid symbol corresponding to Type = %s Variable = %s (so it is not declared in the local scope) \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif // currentStatementList.push_front(*transformationStatementIterator); } #if 0 printf ("BOTTOM OF LOOP OVER VARIABLES: previousStatementCounter = %d \n",previousStatementCounter); #endif } if (statementCounter > previousStatementCounter) previousStatementCounter = statementCounter; #if 0 printf ("BOTTOM OF LOOP OVER TYPES: previousStatementCounter = %d \n",previousStatementCounter); #endif #if 0 printf ("Exiting in insertSourceCode(): transformationStatementIterator loop (type = %s) ... \n",(*typeListStringElementIterator).c_str()); ROSE_ABORT(); #endif } #if 0 printf ("Exiting in loop insertSourceCode (type = %s) ... \n",(*typeListStringElementIterator).c_str()); ROSE_ABORT(); #endif // Now append the new statement AFTER the declaration that we have found // currentStatementList.insert(*targetDeclarationStatementIterator,*transformationStatementIterator); // currentStatementList.insert(lastStatementIterator,*transformationStatementIterator); #if 1 // printf ("BEFORE ADDING NEW STATEMENT: previousStatementCounter = %d \n",previousStatementCounter); if (previousStatementCounter == 0) { printf ("##### Prepend new statement to the top of the local scope \n"); // currentStatementList.push_front(*transformationStatementIterator); currentBlock->prepend_statement (*transformationStatementIterator); } else { // printf ("##### Append the new statement after the last position where a dependent variable is declared in the local scope \n"); // Use new function added to append/prepend at a specified location in the list of statements currentBlock->append_statement (furthestDeclarationInSourceSequence,*transformationStatementIterator); } #else SgStatementPtrList::iterator tempIterator = furthestDeclarationInSourceSequence; tempIterator++; // Handle the case of appending at the end of the list if ( tempIterator == currentStatementList.end() ) { currentBlock->append_statement (*transformationStatementIterator); } else { currentBlock->insert_statement (tempIterator,*transformationStatementIterator); } #endif } else { // This statement has no type information (so it has no dependence upon any non-primative type) // "int x;" would be an example of a statement that would not generate a type (though perhaps it should?) // printf ("This statement has no type information (so it has no dependence upon any non-primative type) \n"); // So this statment can be places at the front of the list of statements in this block // *** Note that we can't use the STL function directly since it does not set the parent information *** // currentStatementList.push_front(*transformationStatementIterator); currentBlock->insert_statement (currentStatementList.begin(),*transformationStatementIterator); } #if 0 string bottomUnparsedDeclarationCodeString = (*transformationStatementIterator)->unparseToString(); ROSE_ASSERT (bottomUnparsedDeclarationCodeString.c_str() != NULL); printf ("bottomUnparsedDeclarationCodeString = %s \n",bottomUnparsedDeclarationCodeString.c_str()); #endif } #if 0 printf ("Exiting in insertSourceCode(): case of locateNewCodeAtTop == true ... \n"); ROSE_ABORT(); #endif } else { // Put the new statements at the end of the list (traverse the new statements from first to last) // But put it before any return statement! So find the last statement! SgStatementPtrList::iterator lastStatement = currentStatementList.begin(); bool foundEndOfList = false; while ( (foundEndOfList == false) && (lastStatement != currentStatementList.end()) ) { SgStatementPtrList::iterator tempStatement = lastStatement; tempStatement++; if (tempStatement == currentStatementList.end()) foundEndOfList = true; else lastStatement++; } ROSE_ASSERT ( *lastStatement != NULL ); // printf ("(*lastStatement)->sage_class_name() = %s \n",(*lastStatement)->sage_class_name()); // printf ("Insert new statements at the bottom of the block \n"); SgStatementPtrList::iterator transformationStatementIterator; for (transformationStatementIterator = newTransformationStatementListPtr->begin(); transformationStatementIterator != newTransformationStatementListPtr->end(); transformationStatementIterator++) { // If there is a RETURN_STMT in the block then insert the new statement just before the // existing RETURN_STMT if ( (*lastStatement)->variant() == RETURN_STMT) { // printf ("Backing away from the end of the list to find the last non-return statement \n"); // lastStatement--; currentBlock->insert_statement(lastStatement,*transformationStatementIterator); } else { currentStatementList.push_back(*transformationStatementIterator); } } } // printf ("$CLASSNAME::insertSourceCode taking (SgProject,char*,char*) not implemented yet! \n"); // ROSE_ABORT(); }
// Do finite differencing on one expression within one context. The expression // must be defined and valid within the entire body of root. The rewrite rules // are used to simplify expressions. When a variable var is updated from // old_value to new_value, an expression of the form (var, (old_value, // new_value)) is created and rewritten. The rewrite rules may either produce // an arbitrary expression (which will be used as-is) or one of the form (var, // (something, value)) (which will be changed to (var = value)). void doFiniteDifferencingOne(SgExpression* e, SgBasicBlock* root, RewriteRule* rules) { SgStatementPtrList& root_stmts = root->get_statements(); SgStatementPtrList::iterator i; for (i = root_stmts.begin(); i != root_stmts.end(); ++i) { if (expressionComputedIn(e, *i)) break; } if (i == root_stmts.end()) return; // Expression is not used within root, so quit vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e); SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter; SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */); SgInitializedName* cachevar = cachedecl->get_variables().back(); ROSE_ASSERT (cachevar); root->get_statements().insert(i, cachedecl); cachedecl->set_parent(root); cachedecl->set_definingDeclaration(cachedecl); cachevar->set_scope(root); SgVariableSymbol* sym = new SgVariableSymbol(cachevar); root->insert_symbol(cachename, sym); SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym); vr->set_endOfConstruct(SgNULL_FILE); replaceCopiesOfExpression(e, vr, root); vector<SgExpression*> modifications_to_used_symbols; FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root); cachedecl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + cachename.str() + " is a cache of " + e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before)); if (modifications_to_used_symbols.size() == 0) { SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e); e->set_parent(cacheinit); cachevar->set_initializer(cacheinit); cacheinit->set_parent(cachevar); } else { for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i) { SgExpression* modstmt = modifications_to_used_symbols[i]; #ifdef FD_DEBUG cout << "Updating cache after " << modstmt->unparseToString() << endl; #endif SgExpression* updateCache = 0; SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym); varref->set_endOfConstruct(SgNULL_FILE); SgTreeCopy tc; SgExpression* eCopy = isSgExpression(e->copy(tc)); switch (modstmt->variantT()) { case V_SgAssignOp: { SgAssignOp* assignment = isSgAssignOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); replaceCopiesOfExpression(lhs, rhs, eCopy); } break; case V_SgPlusAssignOp: case V_SgMinusAssignOp: case V_SgAndAssignOp: case V_SgIorAssignOp: case V_SgMultAssignOp: case V_SgDivAssignOp: case V_SgModAssignOp: case V_SgXorAssignOp: case V_SgLshiftAssignOp: case V_SgRshiftAssignOp: { SgBinaryOp* assignment = isSgBinaryOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); SgTreeCopy tc; SgExpression* rhsCopy = isSgExpression(rhs->copy(tc)); SgExpression* newval = 0; switch (modstmt->variantT()) { #define DO_OP(op, nonassignment) \ case V_##op: { \ newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \ newval->set_endOfConstruct(SgNULL_FILE); \ } \ break DO_OP(SgPlusAssignOp, SgAddOp); DO_OP(SgMinusAssignOp, SgSubtractOp); DO_OP(SgAndAssignOp, SgBitAndOp); DO_OP(SgIorAssignOp, SgBitOrOp); DO_OP(SgMultAssignOp, SgMultiplyOp); DO_OP(SgDivAssignOp, SgDivideOp); DO_OP(SgModAssignOp, SgModOp); DO_OP(SgXorAssignOp, SgBitXorOp); DO_OP(SgLshiftAssignOp, SgLshiftOp); DO_OP(SgRshiftAssignOp, SgRshiftOp); #undef DO_OP default: break; } assert (newval); replaceCopiesOfExpression(lhs, newval, eCopy); } break; case V_SgPlusPlusOp: { SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one); add->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(add); one->set_parent(add); replaceCopiesOfExpression(lhs,add,eCopy); } break; case V_SgMinusMinusOp: { SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one); sub->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(sub); one->set_parent(sub); replaceCopiesOfExpression(lhs,sub,eCopy); } break; default: cerr << modstmt->sage_class_name() << endl; assert (false); break; } #ifdef FD_DEBUG cout << "e is " << e->unparseToString() << endl; cout << "eCopy is " << eCopy->unparseToString() << endl; #endif updateCache = doFdVariableUpdate(rules, varref, e, eCopy); #ifdef FD_DEBUG cout << "updateCache is " << updateCache->unparseToString() << endl; #endif if (updateCache) { ROSE_ASSERT(modstmt != NULL); SgNode* ifp = modstmt->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt); modstmt->set_parent(comma); updateCache->set_parent(comma); if (ifp == NULL) { printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str()); modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug"); } ROSE_ASSERT(ifp != NULL); #ifdef FD_DEBUG cout << "New expression is " << comma->unparseToString() << endl; cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl; #endif if (isSgExpression(ifp)) { isSgExpression(ifp)->replace_expression(modstmt, comma); comma->set_parent(ifp); } else { // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!) // cerr << ifp->sage_class_name() << endl; // assert (!"Bad parent type for inserting comma expression"); SgStatement* statement = isSgStatement(ifp); if (statement != NULL) { #ifdef FD_DEBUG printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str()); SgExprStatement* expresionStatement = isSgExprStatement(statement); if (expresionStatement != NULL) { SgExpression* expression = expresionStatement->get_expression(); printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str()); } #endif statement->replace_expression(modstmt, comma); comma->set_parent(statement); } else { ROSE_ASSERT(ifp != NULL); printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str()); ROSE_ASSERT(false); } } #ifdef FD_DEBUG cout << "IFP is now " << ifp->unparseToString() << endl; #endif } } } }
StructLayoutInfo NonpackedTypeLayoutGenerator::layoutType(SgType* t) const { switch (t->variantT()) { case V_SgClassType: { // Also covers structs and unions SgClassDeclaration* decl = isSgClassDeclaration(isSgClassType(t)->get_declaration()); ROSE_ASSERT (decl); decl = isSgClassDeclaration(decl->get_definingDeclaration()); ROSE_ASSERT (decl); SgClassDefinition* def = decl->get_definition(); ROSE_ASSERT (def); StructLayoutInfo layout; size_t currentOffset = 0; const SgBaseClassPtrList& bases = def->get_inheritances(); for (SgBaseClassPtrList::const_iterator i = bases.begin(); i != bases.end(); ++i) { SgBaseClass* base = *i; SgClassDeclaration* basecls = base->get_base_class(); layoutOneField(basecls->get_type(), base, false, currentOffset, layout); } const SgDeclarationStatementPtrList& body = def->get_members(); bool isUnion = (decl->get_class_type() == SgClassDeclaration::e_union); for (SgDeclarationStatementPtrList::const_iterator i = body.begin(); i != body.end(); ++i) { SgDeclarationStatement* mem = *i; SgVariableDeclaration* vardecl = isSgVariableDeclaration(mem); SgClassDeclaration* classdecl = isSgClassDeclaration(mem); bool isUnnamedUnion = classdecl ? classdecl->get_isUnNamed() : false; if (vardecl) { if (!vardecl->get_declarationModifier().isDefault()) continue; // Static fields and friends ROSE_ASSERT (!vardecl->get_bitfield()); const SgInitializedNamePtrList& vars = isSgVariableDeclaration(mem)->get_variables(); for (SgInitializedNamePtrList::const_iterator j = vars.begin(); j != vars.end(); ++j) { SgInitializedName* var = *j; layoutOneField(var->get_type(), var, isUnion, currentOffset, layout); } } else if (isUnnamedUnion) { layoutOneField(classdecl->get_type(), classdecl, isUnion, currentOffset, layout); } // else continue; } if (layout.alignment != 0 && layout.size % layout.alignment != 0) { size_t paddingNeeded = layout.alignment - (layout.size % layout.alignment); if (!isUnion) { layout.fields.push_back(StructLayoutEntry(NULL, layout.size, paddingNeeded)); } layout.size += paddingNeeded; } return layout; } case V_SgArrayType: { StructLayoutInfo layout = this->beginning->layoutType(isSgArrayType(t)->get_base_type()); layout.fields.clear(); SgExpression* numElements = isSgArrayType(t)->get_index(); //Adjustment for UPC array like a[100*THREADS],treat it as a[100] // Liao, 8/7/2008 if (isUpcArrayWithThreads(isSgArrayType(t))) { SgMultiplyOp* multiply = isSgMultiplyOp(isSgArrayType(t)->get_index()); ROSE_ASSERT(multiply); // DQ (9/26/2011): Do constant folding if required. // SageInterface::constantFolding(multiply); numElements = multiply->get_lhs_operand(); } if (!isSgValueExp(numElements)) { cerr << "Error: trying to compute static size of an array with non-constant size" << endl; abort(); } layout.size *= SageInterface::getIntegerConstantValue(isSgValueExp(numElements)); return layout; } case V_SgTypeComplex: { //"Each complex type has the same representation and alignment requirements as //an array type containing exactly two elements of the corresponding real type" StructLayoutInfo layout = this->beginning->layoutType(isSgTypeComplex(t)->get_base_type()); layout.size *= 2; return layout; } case V_SgTypeImaginary: { StructLayoutInfo layout = this->beginning->layoutType(isSgTypeImaginary(t)->get_base_type()); return layout; } default: return ChainableTypeLayoutGenerator::layoutType(t); } }
virtual void visit(SgNode* n) { SgVarRefExp* vr = isSgVarRefExp(n); if (vr && vr->get_symbol()->get_declaration() == initname) { switch (vr->get_parent()->variantT()) { case V_SgReturnStmt: case V_SgExprStatement: case V_SgIfStmt: case V_SgWhileStmt: case V_SgDoWhileStmt: case V_SgSwitchStatement: case V_SgCaseOptionStmt: case V_SgForStatement: case V_SgForInitStatement: #ifdef FD_DEBUG cout << "Statement: Variable " << initname->get_name().getString() << " is safe" << endl; #endif // Safe break; case V_SgPlusPlusOp: case V_SgMinusMinusOp: #ifdef FD_DEBUG cout << "Inc/dec: Variable " << initname->get_name().getString() << " is safe" << endl; #endif // Safe break; case V_SgAddOp: case V_SgSubtractOp: case V_SgMinusOp: case V_SgUnaryAddOp: case V_SgNotOp: case V_SgPointerDerefExp: case V_SgBitComplementOp: case V_SgThrowOp: case V_SgEqualityOp: case V_SgLessThanOp: case V_SgLessOrEqualOp: case V_SgGreaterThanOp: case V_SgGreaterOrEqualOp: case V_SgNotEqualOp: case V_SgMultiplyOp: case V_SgDivideOp: case V_SgIntegerDivideOp: case V_SgModOp: case V_SgAndOp: case V_SgOrOp: case V_SgBitAndOp: case V_SgBitOrOp: case V_SgBitXorOp: case V_SgCommaOpExp: case V_SgLshiftOp: case V_SgRshiftOp: case V_SgAssignInitializer: #ifdef FD_DEBUG cout << "Non-mutating: Variable " << initname->get_name().getString() << " is safe" << endl; #endif // Safe break; case V_SgExprListExp: if (isSgFunctionCallExp(n->get_parent()->get_parent())) { if (isPotentiallyModified(vr, n->get_parent()->get_parent())) { #ifdef FD_DEBUG cout << "Function call: Variable " << initname->get_name().getString() << " is unsafe" << endl; #endif safe = false; } } else if (isSgConstructorInitializer(n->get_parent()->get_parent())) { #ifdef FD_DEBUG cout << "Constructor: Variable " << initname->get_name().getString() << " is unsafe" << endl; #endif safe = false; // FIXME: constructors } else { cerr << n->get_parent()->get_parent()->sage_class_name() << endl; assert (!"Unknown SgExprListExp case"); } break; case V_SgAssignOp: case V_SgPlusAssignOp: case V_SgMinusAssignOp: { SgBinaryOp* binop = isSgBinaryOp(vr->get_parent()); SgExpression* rhs = binop->get_rhs_operand(); bool lhs_good = (binop->get_lhs_operand() == vr); #ifdef FD_DEBUG cout << "Assign case for " << initname->get_name().getString() << endl; cout << "lhs_good = " << (lhs_good ? "true" : "false") << endl; #endif SgAddOp* rhs_a = isSgAddOp(rhs); SgExpression* rhs_a_lhs = rhs_a ? rhs_a->get_lhs_operand() : 0; SgExpression* rhs_a_rhs = rhs_a ? rhs_a->get_rhs_operand() : 0; if (lhs_good) { if (isSgValueExp(binop->get_rhs_operand())) { // Safe } else if (isSgVarRefExp(rhs)) { // Safe } else if (isSgCastExp(binop->get_rhs_operand()) && isSgValueExp(isSgCastExp(binop->get_rhs_operand()) ->get_operand())) { // Safe } else if (isSgAssignOp(binop) && rhs_a && ((isSgVarRefExp(rhs_a_lhs) && isSgVarRefExp(rhs_a_lhs)->get_symbol() ->get_declaration() == initname) || (isSgVarRefExp(rhs_a_rhs) && isSgVarRefExp(rhs_a_rhs)->get_symbol() ->get_declaration() == initname))) { // Safe } else { #ifdef FD_DEBUG cout << "Assign: Variable " << initname->get_name().str() << " is unsafe because of " << binop->unparseToString() << ": " << binop->get_rhs_operand()->sage_class_name() << endl; #endif safe = false; } } else { // Safe: RHS of assignment } } break; default: { #ifdef FD_DEBUG cout << "Default: Variable " << initname->get_name().str() << " is unsafe because of " << vr->get_parent()->unparseToString() << ": " << vr->get_parent()->sage_class_name() << endl; #endif safe = false; } break; } } }
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(); } // DQ (2/29/2012): Added typedef names to the generated dot file graphs of the AST. SgTypedefDeclaration* typedefDeclaration = isSgTypedefDeclaration(genericDeclaration); if (typedefDeclaration != NULL) { nodelabel += string("\\n") + typedefDeclaration->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; }
// Do a simple form of finite differencing on all functions contained within // root (which should be a project, file, or function definition). void simpleIndexFiniteDifferencing(SgNode* root) { moveForDeclaredVariables(root); SgNode* proj = root; while (proj && !isSgProject(proj)) proj = proj->get_parent(); ROSE_ASSERT (proj); AstTests::runAllTests(isSgProject(proj)); rewrite(getAlgebraicRules(), root); // This might modify root FdFindFunctionsVisitor ffv; ffv.traverse(root, preorder); for (unsigned int x = 0; x < ffv.functions.size(); ++x) { #ifdef FD_DEBUG cout << "Working on function " << ffv.functions[x]->get_declaration()->get_name().str() << endl; #endif SgBasicBlock* body = ffv.functions[x]->get_body(); FdFindInitnamesVisitor fiv; fiv.traverse(ffv.functions[x]->get_declaration(), preorder); vector<SgInitializedName*> initnames = fiv.initnames; set<SgInitializedName*> safe_vars; for (vector<SgInitializedName*>::iterator i = initnames.begin(); i != initnames.end(); ++i) { SgInitializedName* initname = *i; #ifdef FD_DEBUG cout << "Found variable " << initname->get_name().str() << endl; #endif bool safe = true; IsModifiedBadlyVisitor(initname, safe).traverse(body, preorder); if (safe) safe_vars.insert(initname); #ifdef FD_DEBUG cout << "Variable " << initname->get_name().str() << " is " << (safe ? "" : "not ") << "safe" << endl; #endif } FdFindMultiplicationsVisitor fmv; fmv.traverse(body, postorder); vector<SgMultiplyOp*> mult_exprs; for (unsigned int i = 0; i < fmv.exprs.size(); ++i) { bool alreadyProcessed = false; for (unsigned int j = 0; j < i; ++j) { if (expressionTreeEqual(fmv.exprs[i], fmv.exprs[j])) { alreadyProcessed = true; break; } } if (alreadyProcessed) continue; #ifdef FD_DEBUG cout << "Testing expression " << fmv.exprs[i]->unparseToString() << " for possible FD" << endl; #endif SgExpression* expr1 = fmv.exprs[i]->get_lhs_operand(); SgExpression* expr2 = fmv.exprs[i]->get_rhs_operand(); bool isConst1 = isSgValueExp(expr1); bool isSafeVar1 = isSgVarRefExp(expr1) && safe_vars.find(isSgVarRefExp(expr1)->get_symbol() ->get_declaration()) != safe_vars.end(); bool isGood1 = isConst1 || isSafeVar1; bool isConst2 = isSgValueExp(expr2); bool isSafeVar2 = isSgVarRefExp(expr2) && safe_vars.find(isSgVarRefExp(expr2)->get_symbol() ->get_declaration()) != safe_vars.end(); bool isGood2 = isConst2 || isSafeVar2; #ifdef FD_DEBUG cout << boolalpha << "isGood1 = " << isGood1 << ", isGood2 = " << isGood2 << endl; #endif if (isGood1 && isGood2) { #ifdef FD_DEBUG cout << "Expression is good to run FD on" << endl; #endif mult_exprs.push_back(fmv.exprs[i]); } else { #ifdef FD_DEBUG cout << "Expression is not good to run FD on" << endl; #endif } } for (int i = mult_exprs.size() - 1; i >= 0; --i) doFiniteDifferencingOne(mult_exprs[i], body, getFiniteDifferencingRules()); SgNode* bodyCopyForRewrite = body; rewrite(getAlgebraicRules(), bodyCopyForRewrite); // This might update bodyCopyForRewrite ROSE_ASSERT (isSgBasicBlock(bodyCopyForRewrite)); body = isSgBasicBlock(bodyCopyForRewrite); } }
void SystemDependenceGraph::build() { boost::unordered_map<CFGVertex, Vertex> cfgVerticesToSdgVertices; boost::unordered_map<SgNode*, Vertex> astNodesToSdgVertices; //map<SgFunctionCallExp*, vector<SDGNode*> > funcCallToArgs; vector<CallSiteInfo> functionCalls; map<SgNode*, vector<Vertex> > actualInParameters; map<SgNode*, vector<Vertex> > actualOutParameters; map<SgNode*, Vertex> formalInParameters; map<SgNode*, Vertex> formalOutParameters; vector<SgFunctionDefinition*> funcDefs = SageInterface::querySubTree<SgFunctionDefinition>(project_, V_SgFunctionDefinition); foreach (SgFunctionDefinition* funcDef, funcDefs) { SgFunctionDeclaration* funcDecl = funcDef->get_declaration(); CFG* cfg = new CFG(funcDef, cfgNodefilter_); functionsToCFGs_[funcDecl] = cfg; // For each function, build an entry node for it. SDGNode* entry = new SDGNode(SDGNode::Entry); entry->astNode = funcDef; //entry->funcDef = funcDef; Vertex entryVertex = addVertex(entry); functionsToEntries_[funcDecl] = entryVertex; // Add all out formal parameters to SDG. const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); foreach (SgInitializedName* initName, formalArgs) { // If the parameter is passed by reference, create a formal-out node. if (isParaPassedByRef(initName->get_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); formalOutNode->astNode = initName; Vertex formalOutVertex = addVertex(formalOutNode); formalOutParameters[initName] = formalOutVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, formalOutVertex); } } // A vertex representing the returned value. Vertex returnVertex; // If the function returns something, build a formal-out node. if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); // Assign the function declaration to the AST node of this vertex to make // it possible to classify this node into the subgraph of this function. formalOutNode->astNode = funcDecl; returnVertex = addVertex(formalOutNode); formalOutParameters[funcDecl] = returnVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, returnVertex); } // Add all CFG vertices to SDG. foreach (CFGVertex cfgVertex, boost::vertices(*cfg)) { if (cfgVertex == cfg->getEntry() || cfgVertex == cfg->getExit()) continue; SgNode* astNode = (*cfg)[cfgVertex]->getNode(); // If this node is an initialized name and it is a parameter, make it // as a formal in node. SgInitializedName* initName = isSgInitializedName(astNode); if (initName && isSgFunctionParameterList(initName->get_parent())) { SDGNode* formalInNode = new SDGNode(SDGNode::FormalIn); formalInNode->astNode = initName; Vertex formalInVertex = addVertex(formalInNode); formalInParameters[initName] = formalInVertex; cfgVerticesToSdgVertices[cfgVertex] = formalInVertex; astNodesToSdgVertices[astNode] = formalInVertex; // Add a CD edge from call node to this formal-in node. addTrueCDEdge(entryVertex, formalInVertex); continue; } // Add a new node to SDG. SDGNode* newSdgNode = new SDGNode(SDGNode::ASTNode); //newSdgNode->cfgNode = (*cfg)[cfgVertex]; newSdgNode->astNode = astNode; Vertex sdgVertex = addVertex(newSdgNode); cfgVerticesToSdgVertices[cfgVertex] = sdgVertex; astNodesToSdgVertices[astNode] = sdgVertex; // Connect a vertex containing the return statement to the formal-out return vertex. if (isSgReturnStmt(astNode) || isSgReturnStmt(astNode->get_parent())) { SDGEdge* newEdge = new SDGEdge(SDGEdge::DataDependence); addEdge(sdgVertex, returnVertex, newEdge); } // If this CFG node contains a function call expression, extract its all parameters // and make them as actual-in nodes. if (SgFunctionCallExp* funcCallExpr = isSgFunctionCallExp(astNode)) { CallSiteInfo callInfo; callInfo.funcCall = funcCallExpr; callInfo.vertex = sdgVertex; // Change the node type. newSdgNode->type = SDGNode::FunctionCall; vector<SDGNode*> argsNodes; // Get the associated function declaration. SgFunctionDeclaration* funcDecl = funcCallExpr->getAssociatedFunctionDeclaration(); if (funcDecl == NULL) continue; ROSE_ASSERT(funcDecl); const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); SgExprListExp* args = funcCallExpr->get_args(); const SgExpressionPtrList& actualArgs = args->get_expressions(); if (formalArgs.size() != actualArgs.size()) { cout << "The following function has variadic arguments:\n"; cout << funcDecl->get_file_info()->get_filename() << endl; cout << funcDecl->get_name() << formalArgs.size() << " " << actualArgs.size() << endl; continue; } for (int i = 0, s = actualArgs.size(); i < s; ++i) { // Make sure that this parameter node is added to SDG then we // change its node type from normal AST node to a ActualIn arg. ROSE_ASSERT(astNodesToSdgVertices.count(actualArgs[i])); Vertex paraInVertex = astNodesToSdgVertices.at(actualArgs[i]); SDGNode* paraInNode = (*this)[paraInVertex]; paraInNode->type = SDGNode::ActualIn; actualInParameters[formalArgs[i]].push_back(paraInVertex); callInfo.inPara.push_back(paraInVertex); // Add a CD edge from call node to this actual-in node. addTrueCDEdge(sdgVertex, paraInVertex); // If the parameter is passed by reference, create a parameter-out node. if (isParaPassedByRef(formalArgs[i]->get_type())) { SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = actualArgs[i]; //argsNodes.push_back(paraInNode); // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[formalArgs[i]].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } } if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { // If this function returns a value, create a actual-out vertex. SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = funcCallExpr; // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[funcDecl].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); callInfo.isVoid = false; callInfo.returned = paraOutVertex; // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } functionCalls.push_back(callInfo); //funcCallToArgs[funcCallExpr] = argsNodes; } } // Add control dependence edges. addControlDependenceEdges(cfgVerticesToSdgVertices, *cfg, entryVertex); }
//searches for locations where types may be connected through assignment, passing as argument and returns //then passes the associated node along with the expression to link variables. int Analysis::variableSetAnalysis(SgProject* project, SgType* matchType, bool base){ RoseAst wholeAST(project); list<SgVariableDeclaration*> listOfGlobalVars = SgNodeHelper::listOfGlobalVars(project); if(listOfGlobalVars.size() > 0){ for(auto varDec : listOfGlobalVars){ SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDec); if(!initName) continue; SgInitializer* init = initName->get_initializer(); if(!init) continue; SgType* keyType = initName->get_type(); if(!checkMatch(base, keyType, matchType)) continue; addToMap(varDec, varDec); if(!isArrayPointerType(keyType)) continue; SgExpression* exp = init; linkVariables(varDec, keyType, exp); } } list<SgFunctionDefinition*> listOfFunctionDefinitions = SgNodeHelper::listOfFunctionDefinitions(project); for(auto funDef : listOfFunctionDefinitions){ SgInitializedNamePtrList& initNameList = SgNodeHelper::getFunctionDefinitionFormalParameterList(funDef); SgFunctionDeclaration* funDec = funDef->get_declaration(); if(checkMatch(base, funDec->get_type()->get_return_type(), matchType)) addToMap(funDec, funDec); for(auto init : initNameList) if(checkMatch(base, init->get_type(), matchType)) addToMap(init, init); RoseAst ast(funDef); for(RoseAst::iterator i = ast.begin(); i!=ast.end(); i++){ SgNode* key = nullptr; SgType* keyType = nullptr; SgExpression* exp = nullptr; if(SgAssignOp* assignOp = isSgAssignOp(*i)){ SgExpression* lhs = assignOp->get_lhs_operand(); if(SgVarRefExp* varRef = isSgVarRefExp(lhs)){ keyType = varRef->get_type(); if(!isArrayPointerType(keyType)) continue; SgVariableSymbol* varSym = varRef->get_symbol(); key = varSym->get_declaration()->get_declaration(); } exp = assignOp->get_rhs_operand(); } else if(SgVariableDeclaration* varDec = isSgVariableDeclaration(*i)){ SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDec); if(!initName) continue; if(checkMatch(base, matchType, initName->get_type())) addToMap(varDec, varDec); SgInitializer* init = initName->get_initializer(); if(!init) continue; keyType = initName->get_type(); if(!isArrayPointerType(keyType)) continue; key = initName->get_declaration(); exp = init; } else if(SgFunctionCallExp* callExp = isSgFunctionCallExp(*i)){ SgFunctionDefinition* funDef = SgNodeHelper::determineFunctionDefinition(callExp); if(!funDef) continue; SgInitializedNamePtrList& initNameList = SgNodeHelper::getFunctionDefinitionFormalParameterList(funDef); SgExpressionPtrList& expList = callExp->get_args()->get_expressions(); auto initIter = initNameList.begin(); auto expIter = expList.begin(); while(initIter != initNameList.end()){ if(isArrayPointerType((*initIter)->get_type())){ if(checkMatch(base, matchType, (*initIter)->get_type())) linkVariables((*initIter), (*initIter)->get_type(), (*expIter)); } ++initIter; ++expIter; } } else if(SgReturnStmt* ret = isSgReturnStmt(*i)){ exp = ret->get_expression(); keyType = exp->get_type(); if(!isArrayPointerType(keyType)) continue; key = funDec; } if(!checkMatch(base, keyType, matchType)) continue; if(key && keyType && exp) linkVariables(key, keyType, exp); } } for(auto i = setMap.begin(); i != setMap.end(); ++i){ bool intersect = false; set<SgNode*>* found = nullptr; for(auto j = listSets.begin(); j != listSets.end(); ++j){ intersect = setIntersect(*j, i->second); if((*j)->count(i->first)) intersect = true; if(found != nullptr && intersect){ inPlaceUnion(found, i->second); inPlaceUnion(found, *j); (found)->insert(i->first); j = listSets.erase(j); ++j; } else if(intersect){ inPlaceUnion(*j, i->second); (*j)->insert(i->first); found = *j; } } if(!intersect){ set<SgNode*>* copy = copySet(i->second); copy->insert(i->first); listSets.push_back(copy); } } return 0; }
SgName Unparser_Nameq::lookup_generated_qualified_name ( SgNode* referencedNode ) { // These are all of the types of IR nodes that can reference anything that is qualified. // It is a longer list than I expected (or designed for initially), but still not unreasonable. SgName nameQualifier; if (referencedNode == NULL) { // DQ (6/25/2011): This is the case of the using the unparseToString() function. Our more sophisticated name // qualification support is not possible to support in this case (because we don;'t have the scope from which // to compute the qualified name) and so a fully qualified name is generated by default. // printf ("Note that info.set_reference_node_for_qualification(SgNode*) should have been called before calling this function. \n"); // DQ (6/23/2011): This test fails this assertion: tests/roseTests/programAnalysisTests/testCallGraphAnalysis/test3.C // but allow it to pass as a test. // printf ("WARNING: referencedNode in Unparser_Nameq::lookup_generated_qualified_name() should be a valid pointer! \n"); #if 0 // DQ (3/5/2012): Uncommenting this for debugging. printf ("WARNING: referencedNode in Unparser_Nameq::lookup_generated_qualified_name() should be a valid pointer! \n"); #endif return nameQualifier; } ROSE_ASSERT(referencedNode != NULL); #if 0 printf ("In Unparser_Nameq::lookup_generated_qualified_name(): referencedNode = %p = %s \n",referencedNode,referencedNode->class_name().c_str()); #endif switch (referencedNode->variantT()) { case V_SgInitializedName: { SgInitializedName* initializedName = isSgInitializedName(referencedNode); nameQualifier = initializedName->get_qualified_name_prefix_for_type(); break; } // DQ (12/29/2011): Added cases for new template IR nodes. case V_SgTemplateFunctionDeclaration: case V_SgTemplateMemberFunctionDeclaration: case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: case V_SgTemplateInstantiationFunctionDecl: case V_SgTemplateInstantiationMemberFunctionDecl: { SgFunctionDeclaration* node = isSgFunctionDeclaration(referencedNode); nameQualifier = node->get_qualified_name_prefix_for_return_type(); break; } case V_SgTypedefDeclaration: { SgTypedefDeclaration* node = isSgTypedefDeclaration(referencedNode); nameQualifier = node->get_qualified_name_prefix_for_base_type(); break; } case V_SgTemplateArgument: { #if 0 // DQ (5/4/2013): This was previously disabled, maybe because the SgTemplateArgument is shared between too many declarations (in different scopes). printf ("WARNING: lookup of qualifier prefix from SgTemplateArgument was previously disabled \n"); #endif SgTemplateArgument* node = isSgTemplateArgument(referencedNode); nameQualifier = node->get_qualified_name_prefix_for_type(); break; } // DQ (7/13/2013): I think we need this here, but wait until we generate the error to drive it to be introduced. // Also this does not permit handling of multiple types requiring different name qualification (same as for throw support). // DQ (7/12/2013): Added support to type trait builtin functions case V_SgTypeTraitBuiltinOperator: // DQ (8/19/2013): Added support for constructor initializers that might have an associated // qualified name string associated with the templated class or instantiated template class. case V_SgConstructorInitializer: case V_SgTypeIdOp: case V_SgSizeOfOp: case V_SgNewExp: case V_SgCastExp: { // SgCastExp* node = isSgCastExp(referencedNode); SgExpression* node = isSgExpression(referencedNode); nameQualifier = node->get_qualified_name_prefix_for_referenced_type(); break; } case V_SgClassType: { // These can appear in throw expression lists...ignore for now... // SgType* node = isSgType(referencedNode); // nameQualifier = node->get_qualified_name_prefix_for_type(); // printf ("WARNING: Note that qualified types in throw expression lists are not yet supported... \n"); break; } case V_SgFunctionType: { // These can appear in typedefs of function pointers...ignore for now... // SgType* node = isSgType(referencedNode); // nameQualifier = node->get_qualified_name_prefix_for_type(); // printf ("WARNING: Note that qualified types in function pointer typedefs are not yet supported... \n"); break; } case V_SgTypedefType: { // These can appear in typedef types...ignore for now... // SgType* node = isSgType(referencedNode); // nameQualifier = node->get_qualified_name_prefix_for_type(); // printf ("WARNING: Note that qualified types in typedef types are not yet supported... \n"); break; } #if 0 case V_: { * node = is (referencedNode); nameQualifier = node->get_qualified_name_prefix_for_type(); break; } #endif default: { printf ("In Unparser_Nameq::lookup_generated_qualified_name(): Sorry not implemented case of name qualification for info.get_reference_node_for_qualification() = %s \n",referencedNode->class_name().c_str()); ROSE_ASSERT(false); } } return nameQualifier; }
InterleaveAcrossArraysCheckSynthesizedAttributeType interleaveAcrossArraysCheck::evaluateSynthesizedAttribute ( SgNode* n, SynthesizedAttributesList childAttributes ) { //cout << " Node: " << n->unparseToString() << endl; InterleaveAcrossArraysCheckSynthesizedAttributeType localResult; for (SynthesizedAttributesList::reverse_iterator child = childAttributes.rbegin(); child != childAttributes.rend(); child++) { InterleaveAcrossArraysCheckSynthesizedAttributeType childResult = *child; localResult.isArrayRef |= childResult.isArrayRef; localResult.isFunctionRefExp |= childResult.isFunctionRefExp; } if(isSgVariableDeclaration(n)) { SgVariableDeclaration* varDecl = isSgVariableDeclaration(n); SgInitializedNamePtrList & varList = varDecl->get_variables(); for(SgInitializedNamePtrList::iterator initIter = varList.begin(); initIter!=varList.end() ; initIter++) { SgInitializedName* var = *initIter; ROSE_ASSERT(var!=NULL); SgType *variableType = var->get_type(); ROSE_ASSERT (variableType != NULL); string type = TransformationSupport::getTypeName(variableType); string variableName = var->get_name().str(); //Case 6 if(outputName == variableName) { cout << " ERROR: Substituting Array " << outputName << " already declared in the file." << endl; ROSE_ABORT(); } if(type!="doubleArray" && type !="floatArray" && type!="intArray") return localResult; #if DEBUG cout << " Var Name: " << variableName << " Type: " << type << endl; #endif storeArrayReference(var, variableName, type ); } } else if(isSgPntrArrRefExp(n)) { SgVarRefExp* varRefExp = isSgVarRefExp(isSgPntrArrRefExp(n)->get_lhs_operand()); if(varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT (variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT (initializedName != NULL); string variableName = initializedName->get_name().str(); SgType* type = variableSymbol->get_type(); ROSE_ASSERT (type != NULL); string typeName = TransformationSupport::getTypeName(type); // A++ Supported Arrays if(typeName !="doubleArray" && typeName !="floatArray" && typeName !="intArray") return localResult; // Check if variableName matches the input list if(transformation->containsInput(variableName)) localResult.isArrayRef = true; } } else if(isSgFunctionCallExp(n)) { // Case 1 // Check for array being present in function Call if(localResult.isFunctionRefExp && localResult.isArrayRef) { cout << " ERROR: Array Reference present in a function call " << endl; ROSE_ABORT(); } } else if(isSgFunctionRefExp(n)) { localResult.isFunctionRefExp = true; } else if(isSgStatement(n)) { //Case 2 if(isContigousDecl) { cout << " ERROR: Array Declaration are not contigous. " << endl; ROSE_ABORT(); } } return localResult; }
// 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; }
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()); // For sudo_exec_pty.c also look for siginfo if (className == "sigaction" || className == "siginfo") { // 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; // We are puting out all macros anytime we see either type. This might be too much... // From the sigaction.h file (included by signal.h): addMacro(associatedStatement,"#undef sa_handler\n",directiveType); addMacro(associatedStatement,"#undef sa_sigaction\n",directiveType); // From the siginfo.h file (included by signal.h): addMacro(associatedStatement,"#undef si_pid\n", directiveType); addMacro(associatedStatement,"#undef si_uid\n", directiveType); addMacro(associatedStatement,"#undef si_timerid\n",directiveType); addMacro(associatedStatement,"#undef si_overrun\n",directiveType); addMacro(associatedStatement,"#undef si_status\n", directiveType); addMacro(associatedStatement,"#undef si_utime\n", directiveType); addMacro(associatedStatement,"#undef si_stime\n", directiveType); addMacro(associatedStatement,"#undef si_value\n", directiveType); addMacro(associatedStatement,"#undef si_int\n", directiveType); addMacro(associatedStatement,"#undef si_ptr\n", directiveType); addMacro(associatedStatement,"#undef si_addr\n", directiveType); addMacro(associatedStatement,"#undef si_band\n", directiveType); addMacro(associatedStatement,"#undef si_fd\n", directiveType); } } } } default: { // printf ("Not handled in FixupSelfReferentialMacrosInAST::visit(%s) \n",node->class_name().c_str()); } } #if 0 // DQ (12/30/2013): Comments and CPP directives have not yet been attached to the AST, so we can't process them here. // SgLocatedNode* locatedNode = isSgLocatedNode(node); // if (locatedNode != NULL) SgStatement* stmt = isSgStatement(node); if (stmt != NULL) { // Find all #define statements and look for self referencing macros int numberOfComments = -1; if (stmt->getAttachedPreprocessingInfo() != NULL) numberOfComments = stmt->getAttachedPreprocessingInfo()->size(); std::string s = std::string(" --- startOfConstruct: file = " ) + stmt->get_startOfConstruct()->get_filenameString() + " raw filename = " + stmt->get_startOfConstruct()->get_raw_filename() + " raw line = " + StringUtility::numberToString(stmt->get_startOfConstruct()->get_raw_line()) + " raw column = " + StringUtility::numberToString(stmt->get_startOfConstruct()->get_raw_col()) + " #comments = " + StringUtility::numberToString(numberOfComments) + " \n "; AttachedPreprocessingInfoType* comments = stmt->getAttachedPreprocessingInfo(); if (comments != NULL) { printf ("Found attached comments (at %p of type: %s): \n",stmt,stmt->class_name().c_str()); AttachedPreprocessingInfoType::iterator i; for (i = comments->begin(); i != comments->end(); i++) { ROSE_ASSERT ( (*i) != NULL ); printf (" Attached Comment (relativePosition=%s): %s\n", ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after", (*i)->getString().c_str()); printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString()); (*i)->get_file_info()->display("comment/directive location"); } } else { printf ("No attached comments (at %p of type: %s): \n",stmt,stmt->class_name().c_str()); } } #endif }