// Check if this is an A++ Array Reference bool isAPPArray(SgNode *astNode) { SgVarRefExp* varRefExp = isSgVarRefExp(astNode); if (varRefExp == NULL) return false; SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT(initializedName != NULL); SgName variableName = initializedName->get_name(); // 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") { return true; } return false; }
int main(int argc, char* argv[]) { SgProject* project = frontend(argc, argv); std::vector<SgIfStmt*> ifs = SageInterface::querySubTree<SgIfStmt>(project, V_SgIfStmt); BOOST_FOREACH(SgIfStmt* if_stmt, ifs) { if (SgExpression *se = isSgExprStatement(if_stmt->get_conditional())->get_expression()) { cout << "--->" << se->unparseToString() << "<---" << endl; Rose_STL_Container<SgNode*> variableList = NodeQuery::querySubTree(se, V_SgVarRefExp); for (Rose_STL_Container<SgNode*>::iterator i = variableList.begin(), end = variableList.end(); i != end; i++) { SgVarRefExp *varRef = isSgVarRefExp(*i); SgVariableSymbol *currSym = varRef->get_symbol(); cout << "Looking at: --|" << currSym->get_name().str() << "|--" << endl; SgDeclarationStatement *decl = currSym->get_declaration()->get_declaration(); cout << "declaration: " << decl->unparseToString() << endl; SgConstVolatileModifier cvm = decl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); bool constness = cvm.isConst(); cout << "constness via isConst(): " << constness << endl; cout << cvm.displayString() << endl; } } } return 0; }
std::string getSgVarRefExp(SgVarRefExp* varRefExp) { SgVariableSymbol* varSym = varRefExp->get_symbol(); std::string varName; if (SymbolToZ3.find(varSym) == SymbolToZ3.end()) { #ifndef ALLOW_UNKNOWN_VARIABLE_SYMBOL std::cout << "ERROR, unknown variable symbol" << std::endl; ROSE_ASSERT(false); #endif SgInitializedName* initNam = varSym->get_declaration(); ROSE_ASSERT(SymbolToInstances.find(varSym) == SymbolToInstances.end()); std::string init_str = initializeVariable(initNam); declarations.push_back(init_str); std::string retStr = getSgVarRefExp(varRefExp); return retStr; //ROSE_ASSERT(SymbolToInstances.find(varSym) == SymbolToInstan //sitd::cout << "ERROR, unknown variable symbol referenced!" << std::endl; //ROSE_ASSERT(false); } else { varName = SymbolToZ3[varSym]; } int instance = SymbolToInstances[varSym]; std::stringstream varNameStr; varNameStr << varName << "_" << instance; return varNameStr.str(); }
/* * Maintain set of all global variables needed so we can register/unregister * them */ void saveGlobalVariables(PragmaParser* pp, set<SgInitializedName*>& globalVars, SgScopeStatement* scope) { set<string> names = pp->getNames(); set<string>::const_iterator nameIt; for(nameIt = names.begin(); nameIt != names.end(); nameIt++) { SgName curVarName(*nameIt); if(curVarName.getString().rfind('*') != string::npos) curVarName.getString().resize(curVarName.getString().length() - 1); SgVariableSymbol* varSymbol = lookupVariableSymbolInParentScopes(curVarName, scope); ROSE_ASSERT(varSymbol); if(globalVars.find(varSymbol->get_declaration()) == globalVars.end()) globalVars.insert(varSymbol->get_declaration()); } }
SgVariableSymbol* FailSafe::Attribute::addVariable(fail_safe_enum targetConstruct, const std::string& varString, SgInitializedName* sgvar/*=NULL*/) { SgVariableSymbol* symbol = NULL; // Try to resolve the variable if SgInitializedName is not provided if ((sgvar == NULL)&&(mNode!=NULL)) { SgScopeStatement* scope = SageInterface::getScope(mNode); ROSE_ASSERT(scope!=NULL); //resolve the variable here symbol = lookupVariableSymbolInParentScopes (varString, scope); if (symbol == NULL) { cerr<<"Error: FailSafe::Attribute::addVariable() cannot find symbol for variable:"<<varString<<endl; ROSE_ASSERT(symbol!= NULL); } else sgvar = symbol->get_declaration(); } if (sgvar != NULL) { symbol = isSgVariableSymbol(sgvar->get_symbol_from_symbol_table()); // Liao, 3/7/2013. this may end up with infinite search through cyclic graph. //symbol = isSgVariableSymbol(sgvar->search_for_symbol_from_symbol_table ()); } //debug clause var_list // if (targetConstruct== e_copyin) cout<<"debug: adding variable to copyin()"<<endl; variable_lists[targetConstruct].push_back(make_pair(varString, sgvar)); // maintain the var-clause map also var_clauses[varString].push_back(targetConstruct); // Don't forget this! // variable lists are mostly associated with clauses. //But directive like threadprivate could have variable list also if (isClause(targetConstruct)) addClause(targetConstruct); return symbol; }
//Searches through the expression for variables of the given type then links them with the key node provided void Analysis::linkVariables(SgNode* key, SgType* type, SgExpression* expression){ RoseAst ast(expression); for(RoseAst::iterator i = ast.begin(); i!=ast.end(); i++){ if(SgExpression* exp = isSgExpression(*i)){ if(sameType(exp->get_type(), type)){ if(SgFunctionCallExp* funCall = isSgFunctionCallExp(exp)){ SgFunctionDeclaration* funDec = funCall->getAssociatedFunctionDeclaration(); SgFunctionDefinition* funDef = SgNodeHelper::determineFunctionDefinition(funCall); if(!funDef) continue; funDec = funDef->get_declaration(); addToMap(key, funDec); i.skipChildrenOnForward(); } else if(SgPntrArrRefExp* refExp = isSgPntrArrRefExp(exp)){ linkVariables(key, refExp->get_lhs_operand()->get_type(), refExp->get_lhs_operand()); i.skipChildrenOnForward(); } else if(SgPointerDerefExp* refExp = isSgPointerDerefExp(exp)){ linkVariables(key, refExp->get_operand()->get_type(), refExp->get_operand()); i.skipChildrenOnForward(); } else if(SgVarRefExp* varRef = isSgVarRefExp(exp)){ SgVariableSymbol* varSym = varRef->get_symbol(); if(varSym){ SgInitializedName* refInitName = varSym->get_declaration(); SgNode* target = refInitName; if(!SgNodeHelper::isFunctionParameterVariableSymbol(varSym)) target = refInitName->get_declaration(); if(target){ addToMap(key, target); } } } } } } }
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); }
StencilEvaluation_InheritedAttribute StencilEvaluationTraversal::evaluateInheritedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute ) { #if 0 printf ("In evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundPairShiftDoubleConstructor = false; // This is for stencil specifications using vectors of points to represent offsets (not finished). // bool foundVariableDeclarationForStencilInput = false; double stencilCoeficientValue = 0.0; // StencilOffsetFSM offset; StencilOffsetFSM* stencilOffsetFSM = NULL; // We want to interogate the SgAssignInitializer, but we need to generality in the refactored function to use any SgInitializer (e.g. SgConstructorInitializer, etc.). SgInitializedName* initializedName = detectVariableDeclarationOfSpecificType (astNode,"Point"); if (initializedName != NULL) { // This is the code that is specific to the DSL (e.g. the semantics of getZeros() and getUnitv() functions). // So this may be the limit of what can be refactored to common DSL support code. // Or I can maybe do a second pass at atempting to refactor more code later. string name = initializedName->get_name(); SgInitializer* initializer = initializedName->get_initptr(); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); if (assignInitializer != NULL) { SgExpression* exp = assignInitializer->get_operand(); ROSE_ASSERT(exp != NULL); SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(exp); if (functionCallExp != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); string functionName = functionSymbol->get_name(); #if 0 printf ("functionName = %s \n",functionName.c_str()); #endif if (functionName == "getZeros") { // We leverage the semantics of known functions used to initialize "Point" objects ("getZeros" initialized the Point object to be all zeros). // In a stencil this will be the center point from which all other points will have non-zero offsets. // For a common centered difference discretization this will be the center point of the stencil. #if 0 printf ("Identified and interpreting the semantics of getZeros() function \n"); #endif stencilOffsetFSM = new StencilOffsetFSM(0,0,0); ROSE_ASSERT(stencilOffsetFSM != NULL); } if (functionName == "getUnitv") { // We leverage the semantics of known functions used to initialize "Point" objects // ("getUnitv" initializes the Point object to be a unit vector for a specific input dimention). // In a stencil this will be an ofset from the center point. #if 0 printf ("Identified and interpreting the semantics of getUnitv() function \n"); #endif // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); // ROSE_ASSERT(intVal != NULL); if (intVal != NULL) { int value = intVal->get_value(); #if 0 printf ("value = %d \n",value); #endif switch(value) { case 0: stencilOffsetFSM = new StencilOffsetFSM(1,0,0); break; case 1: stencilOffsetFSM = new StencilOffsetFSM(0,1,0); break; case 2: stencilOffsetFSM = new StencilOffsetFSM(0,0,1); break; default: { printf ("Error: default reached in switch: value = %d (for be value of 0, 1, or 2) \n",value); ROSE_ASSERT(false); } } ROSE_ASSERT(stencilOffsetFSM != NULL); // End of test for intVal != NULL } else { #if 0 printf ("functionArg = %p = %s \n",functionArg,functionArg->class_name().c_str()); #endif } } // ROSE_ASSERT(stencilOffsetFSM != NULL); } } } if (stencilOffsetFSM != NULL) { // Put the FSM into the map. #if 0 printf ("Put the stencilOffsetFSM = %p into the StencilOffsetMap using key = %s \n",stencilOffsetFSM,name.c_str()); #endif ROSE_ASSERT(StencilOffsetMap.find(name) == StencilOffsetMap.end()); // We have a choice of syntax to add the element to the map. // StencilOffsetMap.insert(pair<string,StencilOffsetFSM*>(name,stencilOffsetFSM)); StencilOffsetMap[name] = stencilOffsetFSM; } // new StencilOffsetFSM(); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Recognize member function calls on "Point" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = false; bool isTemplateFunctionInstantiation = false; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Point",isTemplateClass,"operator*=",isTemplateFunctionInstantiation); if (functionCallExp != NULL) { // This is the DSL specific part (capturing the semantics of operator*= with specific integer values). // The name of the variable off of which the member function is called (variable has type "Point"). ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); bool usingUnaryMinus = false; if (intVal == NULL) { SgMinusOp* minusOp = isSgMinusOp(functionArg); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; intVal = isSgIntVal(minusOp->get_operand()); } } ROSE_ASSERT(intVal != NULL); int value = intVal->get_value(); if (usingUnaryMinus == true) { value *= -1; } #if 0 printf ("value = %d \n",value); #endif // Look up the stencil offset finite state machine ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 stencilOffsetFSM->display("before multiply event"); #endif if (value == -1) { // Execute the event on the finte state machine to accumulate the state. stencilOffsetFSM->operator*=(-1); } else { printf ("Error: constant value other than -1 are not supported \n"); ROSE_ASSERT(false); } #if 0 stencilOffsetFSM->display("after multiply event"); #endif } // Detection of "pair<Shift,double>(xdir,ident)" defined as an event in the stencil finite machine model. // Actually, it is the Stencil that is create using the "pair<Shift,double>(xdir,ident)" that should be the // event so we first detect the SgConstructorInitializer. There is not other code similar to this which // has to test for the template arguments, so this has not yet refactored into the dslSupport.C file. // I will do this later since this is general support that could be resused in other DSL compilers. SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL) { // DQ (10/20/2014): This can sometimes be NULL. // ROSE_ASSERT(constructorInitializer->get_class_decl() != NULL); SgClassDeclaration* classDeclaration = constructorInitializer->get_class_decl(); // ROSE_ASSERT(classDeclaration != NULL); if (classDeclaration != NULL) { #if 0 printf ("constructorInitializer = %p class name = %s \n",constructorInitializer,classDeclaration->get_name().str()); #endif SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classDeclaration); // ROSE_ASSERT(templateInstantiationDecl != NULL); #if 0 if (templateInstantiationDecl != NULL) { printf ("constructorInitializer = %p name = %s template name = %s \n",constructorInitializer,templateInstantiationDecl->get_name().str(),templateInstantiationDecl->get_templateName().str()); } #endif // if (classDeclaration->get_name() == "pair") if (templateInstantiationDecl != NULL && templateInstantiationDecl->get_templateName() == "pair") { // Look at the template parameters. #if 0 printf ("Found template instantiation for pair \n"); #endif SgTemplateArgumentPtrList & templateArgs = templateInstantiationDecl->get_templateArguments(); if (templateArgs.size() == 2) { // Now look at the template arguments and check that they represent the pattern that we are looking for in the AST. // It is not clear now flexible we should be, at present shift/coeficent pairs must be specified exactly one way. SgType* type_0 = templateArgs[0]->get_type(); SgType* type_1 = templateArgs[1]->get_type(); if ( type_0 != NULL && type_1 != NULL) { SgClassType* classType_0 = isSgClassType(type_0); // ROSE_ASSERT(classType_0 != NULL); if (classType_0 != NULL) { SgClassDeclaration* classDeclarationType_0 = isSgClassDeclaration(classType_0->get_declaration()); ROSE_ASSERT(classDeclarationType_0 != NULL); #if 0 printf ("templateArgs[0]->get_name() = %s \n",classDeclarationType_0->get_name().str()); printf ("templateArgs[1]->get_type()->class_name() = %s \n",type_1->class_name().c_str()); #endif bool foundShiftExpression = false; bool foundStencilCoeficient = false; // We might want to be more flexiable about the type of the 2nd parameter (allow SgTypeFloat, SgTypeComplex, etc.). if (classDeclarationType_0->get_name() == "Shift" && type_1->variant() == V_SgTypeDouble) { // Found a pair<Shift,double> input for a stencil. #if 0 printf ("##### Found a pair<Shift,double>() input for a stencil input \n"); #endif // ***************************************************************************************************** // Look at the first parameter to the pair<Shift,double>() constructor. // ***************************************************************************************************** SgExpression* stencilOffset = constructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(stencilOffset != NULL); #if 0 printf ("stencilOffset = %p = %s \n",stencilOffset,stencilOffset->class_name().c_str()); #endif SgConstructorInitializer* stencilOffsetConstructorInitializer = isSgConstructorInitializer(stencilOffset); if (stencilOffsetConstructorInitializer != NULL) { // This is the case of a Shift being constructed implicitly from a Point (doing so more directly would be easier to make sense of in the AST). #if 0 printf ("!!!!! Looking for the stencil offset \n"); #endif ROSE_ASSERT(stencilOffsetConstructorInitializer->get_class_decl() != NULL); SgClassDeclaration* stencilOffsetClassDeclaration = stencilOffsetConstructorInitializer->get_class_decl(); ROSE_ASSERT(stencilOffsetClassDeclaration != NULL); #if 0 printf ("stencilOffsetConstructorInitializer = %p class name = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration->get_name().str()); printf ("stencilOffsetConstructorInitializer = %p class = %p = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration,stencilOffsetClassDeclaration->class_name().c_str()); #endif // This should not be a template instantiation (the Shift is defined to be a noo-template class declaration, not a template class declaration). SgTemplateInstantiationDecl* stencilOffsetTemplateInstantiationDecl = isSgTemplateInstantiationDecl(stencilOffsetClassDeclaration); ROSE_ASSERT(stencilOffsetTemplateInstantiationDecl == NULL); if (stencilOffsetClassDeclaration != NULL && stencilOffsetClassDeclaration->get_name() == "Shift") { // Now we know that the type associated with the first template parameter is associated with the class "Shift". // But we need so also now what the first parametr is associate with the constructor initializer, since it will // be the name of the variable used to interprete the stencil offset (and the name of the variable will be the // key into the map of finite machine models used to accumulate the state of the stencil offsets that we accumulate // to build the stencil. // Now we need the value of the input (computed using it's fine state machine). SgExpression* inputToShiftConstructor = stencilOffsetConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToShiftConstructor != NULL); SgConstructorInitializer* inputToShiftConstructorInitializer = isSgConstructorInitializer(inputToShiftConstructor); if (stencilOffsetConstructorInitializer != NULL) { SgExpression* inputToPointConstructor = inputToShiftConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToPointConstructor != NULL); // This should be a SgVarRefExp (if we strictly follow the stencil specification rules (which are not written down yet). SgVarRefExp* inputToPointVarRefExp = isSgVarRefExp(inputToPointConstructor); if (inputToPointVarRefExp != NULL) { #if 0 printf ("Found varRefExp in bottom of chain of constructors \n"); #endif SgVariableSymbol* variableSymbolForOffset = isSgVariableSymbol(inputToPointVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForOffset != NULL); SgInitializedName* initializedNameForOffset = variableSymbolForOffset->get_declaration(); ROSE_ASSERT(initializedNameForOffset != NULL); SgInitializer* initializer = initializedNameForOffset->get_initptr(); ROSE_ASSERT(initializer != NULL); #if 0 printf ("Found initializedName: name = %s in bottom of chain of constructors: initializer = %p = %s \n",initializedNameForOffset->get_name().str(),initializer,initializer->class_name().c_str()); #endif // Record the name to be used as a key into the map of "StencilOffset" finite state machines. SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); string name = initializedNameForOffset->get_name(); // Look up the current state in the finite state machine for the "Point". // Check that this is a previously defined stencil offset. ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); // StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { printf ("What is this expression: inputToPointConstructor = %p = %s \n",inputToPointConstructor,inputToPointConstructor->class_name().c_str()); ROSE_ASSERT(false); } } #if 0 printf ("Found Shift type \n"); #endif foundShiftExpression = true; } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { // This case for the specification of a Shift in the first argument is not yet supported (need an example of this). printf ("This case of using a shift is not a part of what is supported \n"); } // ***************************************************************************************************** // Look at the second parameter to the pair<Shift,double>(first_parameter,second_parameter) constructor. // ***************************************************************************************************** SgExpression* stencilCoeficent = constructorInitializer->get_args()->get_expressions()[1]; ROSE_ASSERT(stencilCoeficent != NULL); SgVarRefExp* stencilCoeficentVarRefExp = isSgVarRefExp(stencilCoeficent); if (stencilCoeficentVarRefExp != NULL) { // Handle the case where this is a constant SgVarRefExp and the value is available in the declaration. SgVariableSymbol* variableSymbolForConstant = isSgVariableSymbol(stencilCoeficentVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForConstant != NULL); SgInitializedName* initializedNameForConstant = variableSymbolForConstant->get_declaration(); ROSE_ASSERT(initializedNameForConstant != NULL); SgInitializer* initializer = initializedNameForConstant->get_initptr(); ROSE_ASSERT(initializer != NULL); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); SgValueExp* valueExp = isSgValueExp(assignInitializer->get_operand()); bool usingUnaryMinus = false; // ROSE_ASSERT(valueExp != NULL); if (valueExp == NULL) { SgExpression* operand = assignInitializer->get_operand(); SgMinusOp* minusOp = isSgMinusOp(operand); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; valueExp = isSgValueExp(minusOp->get_operand()); } } SgDoubleVal* doubleVal = isSgDoubleVal(valueExp); // ROSE_ASSERT(doubleVal != NULL); double value = 0.0; if (doubleVal == NULL) { // Call JP's function to evaluate the constant expression. ROSE_ASSERT(valueExp == NULL); ROSE_ASSERT(stencilCoeficent != NULL); DSL_Support::const_numeric_expr_t const_expression = DSL_Support::evaluateConstNumericExpression(stencilCoeficent); if (const_expression.hasValue_ == true) { ROSE_ASSERT(const_expression.isIntOnly_ == false); value = const_expression.value_; printf ("const expression evaluated to value = %4.2f \n",value); } else { printf ("constnat value expression could not be evaluated to a constant \n"); ROSE_ASSERT(false); } } else { #if 1 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif value = (usingUnaryMinus == false) ? doubleVal->get_value() : -(doubleVal->get_value()); } #if 1 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { // When we turn on constant folding in the frontend we eveluate directly to a SgDoubleVal. SgDoubleVal* doubleVal = isSgDoubleVal(stencilCoeficent); if (doubleVal != NULL) { ROSE_ASSERT(doubleVal != NULL); #if 0 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif double value = doubleVal->get_value(); #if 0 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { printf ("Error: second parameter in pair for stencil is not a SgVarRefExp (might be explicit value not yet supported) \n"); printf (" --- stencilCoeficent = %p = %s \n",stencilCoeficent,stencilCoeficent->class_name().c_str()); ROSE_ASSERT(false); } } } #if 0 printf ("foundShiftExpression = %s \n",foundShiftExpression ? "true" : "false"); printf ("foundStencilCoeficient = %s \n",foundStencilCoeficient ? "true" : "false"); #endif if (foundShiftExpression == true && foundStencilCoeficient == true) { #if 0 printf ("Found pair<Shift,double>() constructor expression! \n"); #endif foundPairShiftDoubleConstructor = true; } // End of test for classType_0 != NULL } } } } else { #if 0 printf ("This is not a SgConstructorInitializer for the pair templated class \n"); #endif } // End of test for classDeclaration != NULL } } #if 0 printf ("foundPairShiftDoubleConstructor = %s \n",foundPairShiftDoubleConstructor ? "true" : "false"); #endif if (foundPairShiftDoubleConstructor == true) { // This is the recognition of an event for one of the finite state machines we implement to evaluate the stencil at compile time. #if 0 printf ("In evaluateInheritedAttribute(): found pair<Shift,double>() constructor expression! \n"); printf (" --- stencilOffsetFSM = %p \n",stencilOffsetFSM); printf (" --- stencilCoeficientValue = %f \n",stencilCoeficientValue); #endif ROSE_ASSERT(stencilOffsetFSM != NULL); inheritedAttribute.stencilOffsetFSM = stencilOffsetFSM; inheritedAttribute.stencilCoeficientValue = stencilCoeficientValue; #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Construct the return attribute from the modified input attribute. return StencilEvaluation_InheritedAttribute(inheritedAttribute); }
// DQ (4/7/2004): Added to support more general lookup of data in the AST (vector of variants) void* querySolverGrammarElementFromVariantVector ( SgNode * astNode, VariantVector targetVariantVector, NodeQuerySynthesizedAttributeType* returnNodeList ) { // This function extracts type nodes that would not be traversed so that they can // accumulated to a list. The specific nodes collected into the list is controlled // by targetVariantVector. ROSE_ASSERT (astNode != NULL); #if 0 printf ("Inside of void* querySolverGrammarElementFromVariantVector() astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif Rose_STL_Container<SgNode*> nodesToVisitTraverseOnlyOnce; pushNewNode (returnNodeList,targetVariantVector,astNode); vector<SgNode*> succContainer = astNode->get_traversalSuccessorContainer(); vector<pair<SgNode*,string> > allNodesInSubtree = astNode->returnDataMemberPointers(); #if 0 printf ("succContainer.size() = %zu \n",succContainer.size()); printf ("allNodesInSubtree.size() = %zu \n",allNodesInSubtree.size()); #endif if ( succContainer.size() != allNodesInSubtree.size() ) { for (vector<pair<SgNode*,string> >::iterator iItr = allNodesInSubtree.begin(); iItr!= allNodesInSubtree.end(); ++iItr ) { #if 0 if ( iItr->first != NULL ) { // printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); printf ("iItr->first = %p \n",iItr->first); printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); } #endif // DQ (7/27/2014): Check if this is always non-NULL. // ROSE_ASSERT(iItr->first != NULL); #if 0 if (iItr->first != NULL) { // printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d class_name = %s \n",iItr->first->variantT(),iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first = %p \n",iItr->first); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->class_name = %s \n",iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d \n",(int)iItr->first->variantT()); } else { printf ("In querySolverGrammarElementFromVariantVector(): iItr->first == NULL \n"); } #endif SgType* type = isSgType(iItr->first); if ( type != NULL ) { // DQ (1/13/2011): If we have not already seen this entry then we have to chase down possible nested types. // if (std::find(succContainer.begin(),succContainer.end(),iItr->first) == succContainer.end() ) if (std::find(succContainer.begin(),succContainer.end(),type) == succContainer.end() ) { // DQ (1/30/2010): Push the current type onto the list first, then any internal types... pushNewNode (returnNodeList,targetVariantVector,type); // Are there any other places where nested types can be found...? // if ( isSgPointerType(iItr->first) != NULL || isSgArrayType(iItr->first) != NULL || isSgReferenceType(iItr->first) != NULL || isSgTypedefType(iItr->first) != NULL || isSgFunctionType(iItr->first) != NULL || isSgModifierType(iItr->first) != NULL) // if (type->containsInternalTypes() == true) if (type->containsInternalTypes() == true) { #if 0 printf ("If we have not already seen this entry then we have to chase down possible nested types. \n"); // ROSE_ASSERT(false); #endif Rose_STL_Container<SgType*> typeVector = type->getInternalTypes(); #if 0 printf ("----- typeVector.size() = %zu \n",typeVector.size()); #endif Rose_STL_Container<SgType*>::iterator i = typeVector.begin(); while(i != typeVector.end()) { #if 0 printf ("----- internal type = %s \n",(*i)->class_name().c_str()); #endif // DQ (1/16/2011): This causes a test in tests/roseTests/programAnalysisTests/variableLivenessTests // to fail with error "Error :: Number of nodes = 37 should be : 36" // Add this type to the return list of types. pushNewNode (returnNodeList,targetVariantVector,*i); i++; } } // DQ (1/30/2010): Move this code to the top of the basic block. // pushNewNode (returnNodeList,targetVariantVector,iItr->first); // pushNewNode (returnNodeList,targetVariantVector,type); } } } } #if 0 // This code cannot be put here. Since the same SgVarRefExp will also be found during variable substitution phase. // We don't want to replace the original SgVarRefExp!! // Liao 1/19/2011. query the dim_info of SgArrayType associated with SgPntrArrRefExp // e.g. assuming a subtree has a reference to an array, then the variables used to declare the array dimensions should also be treated as referenced/used by the subtree // even though the reference is indirect. // AST should look like: // SgPntrArrRefExp -> SgVarRefExp (lhs) -> SgVariableSymbol(symbol) -> SgInitializedName -> SgArrayType (typeptr) -> SgExprListExp (dim_info) // AST outlining needs to find indirect use of a variable to work properly if (std::find(targetVariantVector.begin(), targetVariantVector.end(), V_SgVarRefExp) != targetVariantVector.end()) // Only do this if SgVarRefExp is of interest { if (SgPntrArrRefExp * arr_exp = isSgPntrArrRefExp(astNode)) { printf("Debug: queryVariant.C Found SgPntrArrRefExp :%p\n", arr_exp); Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp); // find the array reference from the lhs operand, which could be a complex arithmetic expression SgVarRefExp* array_ref = NULL; for (Rose_STL_Container<SgNode*>::iterator iter = refList.begin(); iter !=refList.end(); iter ++) { SgVarRefExp* cur_ref = isSgVarRefExp(*iter); ROSE_ASSERT (cur_ref != NULL); SgVariableSymbol * sym = cur_ref->get_symbol(); ROSE_ASSERT (sym != NULL); SgInitializedName * i_name = sym->get_declaration(); ROSE_ASSERT (i_name != NULL); SgArrayType * a_type = isSgArrayType(i_name->get_typeptr()); if (a_type) { Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp); for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++) { SgVarRefExp* dim_ref = isSgVarRefExp(*iter2); printf("Debug: queryVariant.C Found indirect SgVarRefExp as part of array dimension declaration:%s\n", dim_ref->get_symbol()->get_name().str()); pushNewNode (returnNodeList, targetVariantVector, *iter2); } } } } // end if SgPntrArrRefExp } // end if find() #endif return NULL; } /* End function querySolverUnionFields() */
// 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; }
// 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 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 ProcTraversal::visit(SgNode *node) { if (isSgFunctionDeclaration(node)) { SgFunctionDeclaration *decl = isSgFunctionDeclaration(node); if (decl->get_definition() != NULL) { /* collect statistics */ //AstNumberOfNodesStatistics anons; //anons.traverse(decl, postorder); //original_ast_nodes += anons.get_numberofnodes(); //original_ast_statements += anons.get_numberofstatements(); /* do the real work */ Procedure *proc = new Procedure(); proc->procnum = procnum++; proc->decl = decl; proc->funcsym = isSgFunctionSymbol(decl->get_symbol_from_symbol_table()); if (proc->funcsym == NULL) { #if 0 std::cout << std::endl << "*** NULL function symbol for declaration " << decl->unparseToString() << std::endl << "symbol: " << (void *) decl->get_symbol_from_symbol_table() << (decl->get_symbol_from_symbol_table() != NULL ? decl->get_symbol_from_symbol_table()->class_name() : "") << std::endl << "first nondef decl: " << (void *) decl->get_firstNondefiningDeclaration() << " sym: " << (decl->get_firstNondefiningDeclaration() != NULL ? (void *) decl->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table() : (void *) NULL) << std::endl; #endif if (decl->get_firstNondefiningDeclaration() != NULL) { proc->funcsym = isSgFunctionSymbol(decl ->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table()); } } assert(proc->funcsym != NULL); // GB (2008-05-14): We need two parameter lists: One for the names of the // variables inside the function definition, which is // decl->get_parameterList(), and one that contains any default arguments // the function might have. The default arguments are supposedly // associated with the first nondefining declaration. proc->params = decl->get_parameterList(); SgDeclarationStatement *fndstmt = decl->get_firstNondefiningDeclaration(); SgFunctionDeclaration *fnd = isSgFunctionDeclaration(fndstmt); if (fnd != NULL && fnd != decl) proc->default_params = fnd->get_parameterList(); else proc->default_params = proc->params; SgMemberFunctionDeclaration *mdecl = isSgMemberFunctionDeclaration(decl); if (mdecl) { proc->class_type = isSgClassDefinition(mdecl->get_scope()); std::string name = proc->class_type->get_mangled_name().str(); name += "::"; name += decl->get_name().str(); std::string mname = proc->class_type->get_mangled_name().str(); mname += "::"; mname += decl->get_mangled_name().str(); proc->memberf_name = name; proc->mangled_memberf_name = mname; proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); // GB (2008-05-26): Computing a single this symbol for each // procedure. Thus, this symbol can also be compared by pointer // equality (as is the case for all other symbols). While we're at it, // we also build a VarRefExp for this which can be used everywhere the // this pointer occurs. proc->this_type = Ir::createPointerType( proc->class_type->get_declaration()->get_type()); proc->this_sym = Ir::createVariableSymbol("this", proc->this_type); proc->this_exp = Ir::createVarRefExp(proc->this_sym); } else { proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); proc->class_type = NULL; proc->memberf_name = proc->mangled_memberf_name = ""; proc->this_type = NULL; proc->this_sym = NULL; proc->this_exp = NULL; // GB (2008-07-01): Better resolution of calls to static functions. // This only makes sense for non-member functions. SgStorageModifier &sm = (fnd != NULL ? fnd : decl)->get_declarationModifier().get_storageModifier(); proc->isStatic = sm.isStatic(); // Note that we query the first nondefining declaration for the // static modifier, but we save the file of the *defining* // declaration. This is because the first declaration might be in // some header file, but for call resolution, the actual source // file with the definition is relevant. // Trace back to the enclosing file node. The definition might be // included in foo.c from bar.c, in which case the Sg_File_Info // would refer to bar.c; but for function call resolution, foo.c is // the relevant file. SgNode *p = decl->get_parent(); while (p != NULL && !isSgFile(p)) p = p->get_parent(); proc->containingFile = isSgFile(p); } proc_map.insert(std::make_pair(proc->name, proc)); mangled_proc_map.insert(std::make_pair(proc->mangled_name, proc)); std::vector<SgVariableSymbol* >* arglist = new std::vector<SgVariableSymbol* >(); SgVariableSymbol *this_var = NULL, *this_temp_var = NULL; if (mdecl || decl->get_parameterList() != NULL && !decl->get_parameterList()->get_args().empty()) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); if (mdecl) { // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // this_var = Ir::createVariableSymbol("this", this_type); this_var = proc->this_sym; // std::string varname // = std::string("$") + proc->name + "$this"; // this_temp_var = Ir::createVariableSymbol(varname, proc->this_type); this_temp_var = global_this_variable_symbol; ParamAssignment* paramAssignment = Ir::createParamAssignment(this_var, this_temp_var); proc->arg_block->statements.push_back(paramAssignment); arglist->push_back(this_var); if (proc->name.find('~') != std::string::npos) { arglist->push_back(this_temp_var); } } SgInitializedNamePtrList params = proc->params->get_args(); SgInitializedNamePtrList::const_iterator i; #if 0 int parnum = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(*i); std::stringstream varname; // varname << "$" << proc->name << "$arg_" << parnum++; SgVariableSymbol* var = Ir::createVariableSymbol(varname.str(),(*i)->get_type()); proc->arg_block->statements.push_back(Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #else // GB (2008-06-23): Trying to replace all procedure-specific argument // variables by a global list of argument variables. This means that at // this point, we do not necessarily need to build a complete list but // only add to the CFG's argument list if it is not long enough. size_t func_params = params.size(); size_t global_args = global_argument_variable_symbols.size(); std::stringstream varname; while (global_args < func_params) { varname.str(""); varname << "$tmpvar$arg_" << global_args++; SgVariableSymbol *var = Ir::createVariableSymbol(varname.str(), global_unknown_type); program->global_map[varname.str()] = std::make_pair(var, var->get_declaration()); global_argument_variable_symbols.push_back(var); } // now create the param assignments size_t j = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(params[j]); SgVariableSymbol *var = global_argument_variable_symbols[j]; j++; proc->arg_block->statements.push_back( Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #if 0 // replace the arglist allocated above by the new one; this must be // fixed for this pointers! delete arglist; arglist = &global_argument_variable_symbols; #endif #endif } else { proc->arg_block = NULL; } /* If this is a constructor, call default constructors * of all base classes. If base class constructors are * called manually, these calls will be removed later. */ if (mdecl && strcmp(mdecl->get_name().str(), proc->class_type->get_declaration()->get_name().str()) == 0 && proc->class_type != NULL) { SgBaseClassPtrList::iterator base; for (base = proc->class_type->get_inheritances().begin(); base != proc->class_type->get_inheritances().end(); ++base) { SgClassDeclaration* baseclass = (*base)->get_base_class(); SgVariableSymbol *lhs = Ir::createVariableSymbol("$tmpvar$" + baseclass->get_name(), baseclass->get_type()); program->global_map["$tmpvar$" + baseclass->get_name()] = std::make_pair(lhs, lhs->get_declaration()); SgMemberFunctionDeclaration* fd=get_default_constructor(baseclass); assert(fd); SgType* basetype=baseclass->get_type(); assert(basetype); SgConstructorInitializer *sci = Ir::createConstructorInitializer(fd,basetype); ArgumentAssignment* a = Ir::createArgumentAssignment(lhs, sci); proc->arg_block->statements.push_back(a); // std::string this_called_varname // = std::string("$") + baseclass->get_name() + "$this"; SgVariableSymbol *this_called_var // = Ir::createVariableSymbol(this_called_varname, // baseclass->get_type()); = global_this_variable_symbol; ReturnAssignment* this_ass = Ir::createReturnAssignment(this_var, this_called_var); proc->arg_block->statements.push_back(this_ass); } } if (mdecl && mdecl->get_CtorInitializerList() != NULL && !mdecl->get_CtorInitializerList()->get_ctors().empty()) { SgInitializedNamePtrList cis = mdecl->get_CtorInitializerList()->get_ctors(); SgInitializedNamePtrList::const_iterator i; if (proc->arg_block == NULL) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); } for (i = cis.begin(); i != cis.end(); ++i) { SgVariableSymbol* lhs = Ir::createVariableSymbol(*i); SgAssignInitializer *ai = isSgAssignInitializer((*i)->get_initializer()); SgConstructorInitializer *ci = isSgConstructorInitializer((*i)->get_initializer()); /* TODO: other types of initializers */ if (ai) { SgClassDeclaration *class_decl = proc->class_type->get_declaration(); // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // SgVarRefExp* this_ref // = Ir::createVarRefExp("this", // Ir::createPointerType(class_decl->get_type())); SgVarRefExp* this_ref = proc->this_exp; SgArrowExp* arrowExp = Ir::createArrowExp(this_ref,Ir::createVarRefExp(lhs)); // GB (2008-03-17): We need to handle function calls in // initializers. In order to be able to build an argument // assignment, we need to know the function's return variable, so // the expression labeler must be called on it. The expression // number is irrelevant, however, as it does not appear in the // return variable. if (isSgFunctionCallExp(ai->get_operand_i())) { #if 0 ExprLabeler el(0 /*expnum*/); el.traverse(ai->get_operand_i(), preorder); // expnum = el.get_expnum(); #endif // GB (2008-06-25): There is now a single global return // variable. This may or may not mean that we can simply ignore // the code above. I don't quite understand why this labeling // couldn't be done later on, and where its result was used. } ArgumentAssignment* argumentAssignment = Ir::createArgumentAssignment(arrowExp,ai->get_operand_i()); proc->arg_block->statements.push_back(argumentAssignment); } else if (ci) { /* if this is a call to a base class's * constructor, remove the call we generated * before */ SgStatement* this_a = NULL; SgClassDeclaration* cd = ci->get_class_decl(); std::deque<SgStatement *>::iterator i; for (i = proc->arg_block->statements.begin(); i != proc->arg_block->statements.end(); ++i) { ArgumentAssignment* a = dynamic_cast<ArgumentAssignment *>(*i); if (a && isSgConstructorInitializer(a->get_rhs())) { SgConstructorInitializer* c = isSgConstructorInitializer(a->get_rhs()); std::string c_decl_name = c->get_class_decl()->get_name().str(); std::string cd_name = cd->get_name().str(); // if (c->get_class_decl()->get_name() == cd->get_name()) { if (c_decl_name == cd_name) { #if 0 // erase the following assignment // of the this pointer as well this_a = *proc->arg_block->statements.erase(i+1); proc->arg_block->statements.erase(i); #endif // GB (2008-03-28): That's an interesting piece of code, but // it might be very mean to iterators. At least it is hard to // see whether it is correct. So let's try it like this: // erase i; we get an iterator back, which refers to the next // element. Save that element as this_a, and then erase. std::deque<SgStatement *>::iterator this_pos; this_pos = proc->arg_block->statements.erase(i); this_a = *this_pos; proc->arg_block->statements.erase(this_pos); // Good. Looks like this fixed a very obscure bug. break; } } } /* now add the initialization */ proc->arg_block->statements.push_back(Ir::createArgumentAssignment(lhs, ci)); if (this_a != NULL) proc->arg_block->statements.push_back(this_a); } } } proc->entry = new CallBlock(node_id++, START, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->exit = new CallBlock(node_id++, END, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->entry->partner = proc->exit; proc->exit->partner = proc->entry; proc->entry->call_target = Ir::createFunctionRefExp(proc->funcsym); proc->exit->call_target = Ir::createFunctionRefExp(proc->funcsym); /* In constructors, insert an assignment $A$this = this * at the end to make sure that the 'this' pointer can be * passed back to the calling function uncobbled. */ proc->this_assignment = NULL; if (mdecl) { SgMemberFunctionDeclaration* cmdecl = isSgMemberFunctionDeclaration(mdecl->get_firstNondefiningDeclaration()); // if (cmdecl && cmdecl->get_specialFunctionModifier().isConstructor()) { proc->this_assignment = new BasicBlock(node_id++, INNER, proc->procnum); ReturnAssignment* returnAssignment = Ir::createReturnAssignment(this_temp_var, this_var); proc->this_assignment->statements.push_back(returnAssignment); add_link(proc->this_assignment, proc->exit, NORMAL_EDGE); // } } std::stringstream varname; // varname << "$" << proc->name << "$return"; // proc->returnvar = Ir::createVariableSymbol(varname.str(), // decl->get_type()->get_return_type()); proc->returnvar = global_return_variable_symbol; procedures->push_back(proc); if(getPrintCollectedFunctionNames()) { std::cout << (proc->memberf_name != "" ? proc->memberf_name : proc->name) << " " /*<< proc->decl << std::endl*/; } if (proc->arg_block != NULL) { proc->arg_block->call_target = Ir::createFunctionRefExp(proc->funcsym); } // delete arglist; } } }
bool checkIfNodeMaps(token_type tok, SgNode* node) { bool nodeMaps = false; using namespace boost::wave; //By definition a compiler generated node can //not map to the token stream SgLocatedNode* compilerGeneratedNode = isSgLocatedNode(node); if( compilerGeneratedNode != NULL ) if(compilerGeneratedNode->get_file_info()->isCompilerGenerated() == true) return false; // std::cout << get_token_name(tok) << " " << std::string(tok.get_value().c_str()) << " " << node->class_name() << " " << node->get_file_info()->get_line() << std::endl; //Mapping literal token id's switch(token_id(tok)){ case T_PP_NUMBER:{ if(isSgValueExp(node)!=NULL) nodeMaps=true; break; } case T_CHARLIT:{ if( ( isSgCharVal(node) != NULL ) | ( isSgUnsignedCharVal(node) != NULL ) ) nodeMaps = true; break; } case T_FLOATLIT:{ if( isSgFloatVal(node) != NULL ) nodeMaps = true; break; } case T_INTLIT:{ if( ( isSgIntVal(node) != NULL ) || ( isSgUnsignedIntVal(node) != NULL ) ) nodeMaps = true; break; } case T_LONGINTLIT: { if( ( isSgLongIntVal(node) != NULL ) | ( isSgLongLongIntVal(node) != NULL ) | ( isSgUnsignedLongLongIntVal(node) != NULL ) ) nodeMaps = true; break; } case T_STRINGLIT: { if( isSgStringVal(node) != NULL ) nodeMaps = true; break; } case T_QUESTION_MARK: { if( isSgConditionalExp(node) != NULL ) nodeMaps = true; break; } case T_FALSE: case T_TRUE: if( isSgBoolValExp(node) != NULL ) nodeMaps = true; break; default: break; } //map keyword token id's switch(token_id(tok)){ case T_ASM: if( isSgAsmStmt(node) != NULL ) nodeMaps = true; break; case T_AUTO: //auto //dont know break; /*case T_BOOL: //dont think this can be mapped break;*/ case T_BREAK: if( isSgBreakStmt(node) != NULL ) nodeMaps = true; break; case T_CASE: if( isSgCaseOptionStmt(node) != NULL ) nodeMaps = true; break; case T_CATCH: if( isSgCatchOptionStmt(node) != NULL ) nodeMaps = true; break; /* case T_CHAR: //dont know break; */ case boost::wave::T_CLASS: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_CONST: // is it SgConstVolatileModifier? //dont know break; case T_CONTINUE: if( isSgContinueStmt(node) != NULL ) nodeMaps = true; break; //case T_DEFAULT: //Dont know // break; case T_DELETE: if( isSgDeleteExp(node) != NULL ) nodeMaps = true; break; case T_DO: if( isSgDoWhileStmt(node) != NULL ) nodeMaps = true; break; case T_ELSE: //dont know break; case T_EXPLICIT: //dont know break; case T_EXPORT: case T_EXTERN: break; case T_FOR: if( isSgForStatement(node) != NULL ) nodeMaps = true; break; case T_FRIEND: //dont know break; case T_GOTO: if( isSgGotoStatement(node) != NULL ) nodeMaps = true; break; case T_IF: //dont know how to handle this because if if-else break; case T_INLINE: //dont know break; case T_MUTABLE: //dont know break; case T_NAMESPACE: if( ( isSgNamespaceAliasDeclarationStatement(node) != NULL ) | (isSgNamespaceDeclarationStatement(node) != NULL ) ) nodeMaps = true; break; case T_NEW: if( isSgNewExp(node) != NULL ) nodeMaps = true; break; case T_OPERATOR: case T_PRIVATE: case T_PROTECTED: case T_PUBLIC: case T_REGISTER: case T_REINTERPRETCAST: //dont know break; case T_RETURN: if( isSgReturnStmt(node) != NULL ) nodeMaps = true; break; case T_SIZEOF: if( isSgSizeOfOp(node) != NULL ) nodeMaps = true; break; case T_STATIC: case T_STATICCAST: //dont know break; case T_STRUCT: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_SWITCH: if( isSgSwitchStatement(node) != NULL ) nodeMaps = true; break; //case T_TEMPLATE: //dont know // break; case T_THIS: if( isSgThisExp(node) != NULL ) nodeMaps = true; break; case T_THROW: if( isSgThrowOp(node) != NULL ) nodeMaps = true; break; case T_TRY: if( isSgTryStmt(node) != NULL ) nodeMaps = true; break; case boost::wave::T_TYPEDEF: if( isSgTypedefDeclaration(node) != NULL ) nodeMaps = true; break; case T_TYPEID: if( isSgTypeIdOp(node) != NULL ) nodeMaps = true; break; case T_TYPENAME: //dont know break; case T_UNION: if( isSgClassDeclaration(node) != NULL ) nodeMaps = true; break; case T_USING: if( isSgUsingDeclarationStatement(node) != NULL ) nodeMaps = true; break; case T_VIRTUAL: //dont know break; case T_VOLATILE: //is it SgConstVolatileModifier ? break; case T_WHILE: if( isSgWhileStmt(node) != NULL ) nodeMaps = true; break; default: break; } //map operator token id's switch(token_id(tok)){ case T_AND: case T_ANDAND: if( isSgAndOp(node) != NULL | isSgBitAndOp(node) != NULL ) nodeMaps = true; break; case T_ASSIGN: if ( isSgAssignOp(node) != NULL | isSgAssignInitializer(node) != NULL ) nodeMaps = true; break; case T_ANDASSIGN: //do not know break; case T_OR: if ( isSgBitOrOp(node) != NULL || isSgOrOp(node) != NULL ) nodeMaps = true; break; case T_ORASSIGN: //do not know break; case T_XOR: if ( isSgBitXorOp(node) != NULL ) nodeMaps = true; break; case T_XORASSIGN: if ( isSgXorAssignOp(node) != NULL ) nodeMaps = true; break; case T_COMMA: if ( isSgCommaOpExp(node) != NULL ) nodeMaps = true; break; case T_COLON: //dont know break; case T_DIVIDE: if ( isSgDivideOp(node) != NULL ) nodeMaps = true; break; case T_DIVIDEASSIGN: if ( isSgDivAssignOp(node) != NULL ) nodeMaps = true; break; case T_DOT: if ( isSgDotExp(node) != NULL ) nodeMaps = true; break; case T_DOTSTAR: if ( isSgDotExp(node) != NULL ) nodeMaps = true; break; case T_ELLIPSIS: //Dont know break; case T_EQUAL: if ( isSgEqualityOp(node) != NULL ) nodeMaps = true; break; case T_GREATER: if ( isSgGreaterThanOp(node) != NULL ) nodeMaps = true; break; case T_GREATEREQUAL: if ( isSgGreaterOrEqualOp(node) != NULL ) nodeMaps = true; break; case T_LEFTBRACE: //Dont know break; case T_LESS: if ( isSgLessThanOp(node) != NULL ) nodeMaps = true; break; case T_LESSEQUAL: if ( isSgLessOrEqualOp(node) != NULL ) nodeMaps = true; break; case T_LEFTPAREN: //Dont know break; case T_LEFTBRACKET: case T_RIGHTBRACKET: if ( isSgPntrArrRefExp(node) != NULL ) nodeMaps = true; break; case T_MINUS: if ( ( isSgSubtractOp(node) != NULL ) | ( isSgMinusOp(node) != NULL ) ) nodeMaps = true; break; case T_MINUSASSIGN: if ( isSgMinusAssignOp(node) != NULL ) nodeMaps = true; break; case T_MINUSMINUS: if ( isSgMinusMinusOp(node) != NULL ) nodeMaps = true; break; case T_PERCENT: if ( isSgModOp(node) != NULL ) nodeMaps = true; break; case T_PERCENTASSIGN: if ( isSgModAssignOp(node) != NULL ) nodeMaps = true; break; case T_NOT: if ( isSgNotOp(node) != NULL ) nodeMaps = true; break; case T_NOTEQUAL: if ( isSgNotEqualOp(node) != NULL ) nodeMaps = true; break; case T_OROR: if ( isSgOrOp(node) != NULL ) nodeMaps = true; break; case T_PLUS: if ( isSgAddOp(node) != NULL ) nodeMaps = true; break; case T_PLUSASSIGN: if ( isSgPlusAssignOp(node) != NULL ) nodeMaps = true; break; case T_PLUSPLUS: if ( isSgPlusPlusOp(node) != NULL ) nodeMaps = true; break; case T_ARROW: if ( isSgArrowExp(node) != NULL ) nodeMaps = true; break; case T_ARROWSTAR: if ( isSgArrowStarOp(node) != NULL ) nodeMaps = true; break; case T_QUESTION_MARK: //dont know break; case T_RIGHTBRACE: case T_RIGHTPAREN: case T_COLON_COLON: case T_SEMICOLON: //dont know break; case T_SHIFTLEFT: if ( isSgLshiftOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTLEFTASSIGN: if ( isSgLshiftAssignOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTRIGHT: if ( isSgRshiftOp(node) != NULL ) nodeMaps = true; break; case T_SHIFTRIGHTASSIGN: if ( isSgRshiftAssignOp(node) != NULL ) nodeMaps = true; break; case T_STAR: //dont know if ( isSgMultiplyOp(node) != NULL || isSgPointerType(node) ) nodeMaps = true; break; case T_COMPL://~ if( isSgBitComplementOp(node) != NULL ) nodeMaps = true; //Dont know break; case T_STARASSIGN: if ( isSgMultAssignOp(node) != NULL ) nodeMaps = true; break; case T_POUND_POUND: case T_POUND: //dont know break; case T_AND_ALT: case T_ANDASSIGN_ALT: case T_OR_ALT: case T_ORASSIGN_ALT: case T_XOR_ALT: case T_XORASSIGN_ALT: case T_LEFTBRACE_ALT: case T_LEFTBRACKET_ALT: case T_NOT_ALT: case T_NOTEQUAL_ALT: case T_RIGHTBRACE_ALT: case T_RIGHTBRACKET_ALT: case T_COMPL_ALT: case T_POUND_POUND_ALT: case T_POUND_ALT: case T_OR_TRIGRAPH: case T_XOR_TRIGRAPH: case T_LEFTBRACE_TRIGRAPH: case T_LEFTBRACKET_TRIGRAPH: case T_RIGHTBRACE_TRIGRAPH: case T_RIGHTBRACKET_TRIGRAPH: case T_COMPL_TRIGRAPH: case T_POUND_POUND_TRIGRAPH: case T_POUND_TRIGRAPH: //dont know break; default: break; } switch(token_id(tok)){ case T_FALSE: case T_TRUE: break; case T_CHARLIT: if(SgProject::get_verbose() >= 1) std::cout << "char " << std::string(tok.get_value().c_str()) << std::endl; if( isSgCharVal(node) != NULL ){ SgCharVal* charVal = isSgCharVal(node); if(SgProject::get_verbose() >= 1) std::cout << std::string(tok.get_value().c_str()) << std::endl; char tmp = charVal->get_value(); if(SgProject::get_verbose() >= 1) std::cout << "From charlit: " << tmp << std::endl; if(("\""+std::string(&tmp)+"\"") == std::string(tok.get_value().c_str()) ) nodeMaps = true; } break; case T_STRINGLIT: { if(SgProject::get_verbose() >= 1) std::cout << "string " <<std::string(tok.get_value().c_str()) << std::endl; if( isSgStringVal(node) != NULL ){ SgStringVal* stringVal = isSgStringVal(node); if(SgProject::get_verbose() >= 1){ std::cout << std::string(tok.get_value().c_str()) << std::endl; std::cout << "stringlit: " << stringVal->get_value() << std::endl; } if(("\""+stringVal->get_value()+"\"") == std::string(tok.get_value().c_str()) ) nodeMaps = true; } break; } /*case V_SgWcharVal: if( isSgWcharVal(node) != NULL ) if( std::string(isSgWcharVal(node)->get_value()) == std::string(tok.get_value().c_str()) ) nodeMaps = true; break;*/ default: break; } if( token_id(tok) == T_IDENTIFIER ){ if( isSgInitializedName(node) != NULL ){ std::cout << "Identifier" << std::endl; SgInitializedName* initName = isSgInitializedName(node); std::cout << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; if( initName->get_name().getString() == std::string(tok.get_value().c_str()) ){ nodeMaps = true; } }else if( isSgVarRefExp(node) != NULL ){ SgVariableSymbol* varSymbol = isSgVarRefExp(node)->get_symbol(); SgInitializedName* initName = varSymbol->get_declaration(); if( initName->get_name().getString() == std::string(tok.get_value().c_str()) ){ nodeMaps = true; std::cout << "Maps:" << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; }else std::cout << "DONT Map:" << initName->get_name().getString() << " " << std::string(tok.get_value().c_str()) << std::endl; }else if( isSgFunctionRefExp(node) != NULL){ SgFunctionRefExp* funcRef = isSgFunctionRefExp(node); SgFunctionSymbol* funcSymbol = funcRef->get_symbol_i(); if( funcSymbol->get_declaration()->get_name().getString() == std::string(tok.get_value().c_str()) ) nodeMaps = true; }else if( isSgMemberFunctionRefExp(node) != NULL){ SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(node); SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); if( funcSymbol->get_declaration()->get_name().getString() == std::string(tok.get_value().c_str()) ) nodeMaps = true; } } //Exceptions to the general rule switch(token_id(tok)){ case T_CHARLIT: { switch(node->variantT()) { case V_SgCharVal: case V_SgComplexVal: case V_SgDoubleVal: case V_SgEnumVal: case V_SgFloatVal: case V_SgIntVal: case V_SgLongDoubleVal: case V_SgLongIntVal: case V_SgLongLongIntVal: case V_SgShortVal: case V_SgStringVal: case V_SgUnsignedCharVal: case V_SgUnsignedIntVal: case V_SgUnsignedLongLongIntVal: case V_SgUnsignedLongVal: case V_SgUnsignedShortVal: case V_SgWcharVal: { nodeMaps=true; break; } default: break; }; break; }; } switch(boost::wave::token_id(tok)){ case boost::wave::T_CHAR: { if(isSgTypeChar(node) != NULL) nodeMaps=true; break; } case boost::wave::T_CONST: break; case boost::wave::T_DOUBLE: if(isSgTypeDouble(node) != NULL) nodeMaps=true; break; case boost::wave::T_INT: if(isSgTypeInt(node) != NULL) nodeMaps=true; break; case boost::wave::T_LONG: if(isSgTypeLong(node) != NULL) nodeMaps=true; break; case boost::wave::T_SHORT: if(isSgTypeShort(node) != NULL) nodeMaps=true; break; case boost::wave::T_SIGNED: case boost::wave::T_UNSIGNED: case boost::wave::T_VOID: if(isSgTypeVoid(node) != NULL) nodeMaps=true; break; default: break; }; return nodeMaps; }
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(); }
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; }
//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; }
void CompassAnalyses::VariableNameEqualsDatabaseName::Traversal:: visit(SgNode* node) { if( isSgAssignInitializer(node) != NULL ) assignExp = node; if( isSgAssignOp(node) != NULL ) assignExp = node; SgFunctionCallExp* funcCall = isSgFunctionCallExp(node); // See if we have a dot expression or arrow expression which // accesses the desired member function in the class we are looking for. if ( funcCall != NULL ) { SgExpression* funcExp = funcCall->get_function(); if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) ) { SgBinaryOp* binOp = isSgBinaryOp(funcExp); SgExpression* rhsOp = binOp->get_rhs_operand(); // SgExpression* lhsOp = binOp->get_lhs_operand(); if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp) ) { // std::cout << "c1\n" ; SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); ROSE_ASSERT(funcSymbol->get_declaration() != NULL); // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C) // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL); if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL) { SgMemberFunctionDeclaration* funcDecl = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration()); ROSE_ASSERT( funcDecl != NULL ); SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope()); SgClassDeclaration* clDecl = isSgClassDeclaration(clDef->get_declaration()); // SgClassDeclaration* clDecl = funcDecl->get_associatedClassDeclaration(); ROSE_ASSERT( clDecl != NULL ); std::string className = clDecl->get_name().getString(); ROSE_ASSERT(funcDecl != NULL); std::string functionName = funcDecl->get_name().getString(); // If the class is the class we are looking for see if the member function // access is to the member function we are interested in. // std::cout << "className = " << className << std::endl; // std::cout << "functionName = " << functionName << std::endl; if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) ) { SgExprListExp* actualArgs = funcCall->get_args(); SgExpressionPtrList& actualExpArgs = actualArgs->get_expressions (); ROSE_ASSERT(actualExpArgs.size() == 1); Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal); ROSE_ASSERT( nodeLst.size() > 0); SgStringVal* actualArg = isSgStringVal(*nodeLst.begin()); ROSE_ASSERT(actualArg != NULL); std::string stringArg = actualArg->get_value(); std::cout << "arg:" << stringArg << std::endl; std::string varName; // SgInitializedName* initName = NULL; if ( SgAssignInitializer* assignInit = isSgAssignInitializer(assignExp) ) { SgInitializedName* initName = isSgInitializedName(assignInit->get_parent()); ROSE_ASSERT(initName != NULL); varName = initName->get_name().getString(); } else { if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) ) { SgExpression* lhsOp = assignOp->get_lhs_operand(); SgVarRefExp* varRef = isSgVarRefExp(lhsOp); ROSE_ASSERT(varRef!=NULL); SgVariableSymbol* varSymbol = varRef->get_symbol(); ROSE_ASSERT(varSymbol != NULL); SgInitializedName* initName = varSymbol->get_declaration(); varName = initName->get_name().getString(); } } if (varName != "") { // we are only interested in the part of the argument after the last ":" // Database scopes in ALE3D are separated by ":" size_t posCol = stringArg.find_last_of(':'); if (posCol != std::string::npos) stringArg = stringArg.substr(posCol+1); //Find violations to the rule if ( stringArg != varName) { output->addOutput(new CheckerOutput(assignExp)); std::cout << "violation" << varName << std::endl; } else { std::cout << "non=violation" << varName << std::endl; } } } } } } } } // End of the visit function.
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); } } }