/* * Case to handle interleaveArrayOption * C = interleaveAcrossArrays(A,B); * i/p = A,B ; o/p = C ; operation = interleaveAcrossArrays */ void specificationTraversal::handleInterLeaveAcrossArrays(SgFunctionCallExp* funcCallExp) { ROSE_ASSERT(isSgFunctionCallExp(funcCallExp) != NULL); SgExpressionPtrList& args = funcCallExp->get_args()->get_expressions(); vector < string > inputArgs; vector < string > outputArgs; // Extract the argument and put it into the input list for (SgExpressionPtrList::iterator expr = args.begin(); expr != args.end(); expr++) { SgVarRefExp* varRefExp = isSgVarRefExp(*expr); ROSE_ASSERT(varRefExp != NULL); string argName = varRefExp->get_symbol()->get_declaration()->get_name().getString(); inputArgs.push_back(argName); #if DEBUG cout << " Input Arg: " << argName << endl; #endif } // Extract the output SgAssignOp* assignOp = isSgAssignOp(funcCallExp->get_parent()); SgVarRefExp* outputVarRefExp = isSgVarRefExp(assignOp->get_lhs_operand()); ROSE_ASSERT(outputVarRefExp != NULL); string outputName = outputVarRefExp->get_symbol()->get_declaration()->get_name().getString(); outputArgs.push_back(outputName); #if DEBUG cout << " Output Arg: " << outputName << endl; #endif // Add to worklist transformationWorklist.addToWorklist(LayoutOptions::InterleaveAcrossArrays, inputArgs, outputArgs); }
InheritedAttribute BugSeeding::evaluateInheritedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute ) { // Use this if we only want to seed bugs in loops bool isLoop = inheritedAttribute.isLoop || (isSgForStatement(astNode) != NULL) || (isSgWhileStmt(astNode) != NULL) || (isSgDoWhileStmt(astNode) != NULL); // Add Fortran support isLoop = isLoop || (isSgFortranDo(astNode) != NULL); // Mark future noes in this subtree as being part of a loop inheritedAttribute.isLoop = isLoop; // To test this on simple codes, optionally allow it to be applied everywhere bool applyEveryWhere = true; if (isLoop == true || applyEveryWhere == true) { // The inherited attribute is true iff we are inside a loop and this is a SgPntrArrRefExp. SgPntrArrRefExp *arrayReference = isSgPntrArrRefExp(astNode); if (arrayReference != NULL) { // Mark as a vulnerability inheritedAttribute.isVulnerability = true; // Now change the array index (to seed the buffer overflow bug) SgVarRefExp* arrayVarRef = isSgVarRefExp(arrayReference->get_lhs_operand()); ROSE_ASSERT(arrayVarRef != NULL); ROSE_ASSERT(arrayVarRef->get_symbol() != NULL); SgInitializedName* arrayName = isSgInitializedName(arrayVarRef->get_symbol()->get_declaration()); ROSE_ASSERT(arrayName != NULL); SgArrayType* arrayType = isSgArrayType(arrayName->get_type()); ROSE_ASSERT(arrayType != NULL); SgExpression* arraySize = arrayType->get_index(); SgTreeCopy copyHelp; // Make a copy of the expression used to hold the array size in the array declaration. SgExpression* arraySizeCopy = isSgExpression(arraySize->copy(copyHelp)); ROSE_ASSERT(arraySizeCopy != NULL); // This is the existing index expression SgExpression* indexExpression = arrayReference->get_rhs_operand(); ROSE_ASSERT(indexExpression != NULL); // Build a new expression: "array[n]" --> "array[n+arraySizeCopy]", where the arraySizeCopy is a size of "array" SgExpression* newIndexExpression = buildAddOp(indexExpression,arraySizeCopy); // Substitute the new expression for the old expression arrayReference->set_rhs_operand(newIndexExpression); } } return inheritedAttribute; }
virtual void visit(SgNode* n) { if (isSgVarRefExp(n)) { SgVarRefExp* vr = isSgVarRefExp(n); assert (vr->get_symbol()); if (vr->get_symbol()->get_declaration() == initname) { if (inSimpleContext(vr) || !needSimpleContext) { SgTreeCopy tc; isSgExpression(n->get_parent())->replace_expression( vr, isSgExpression(initexpr->copy(tc))); } } } }
/** * Matches assignment statements (including pointer association) */ void FortranAnalysis::visit(SgExprStatement * expr_stmt) { if (matchRegionAssignment(expr_stmt)) { SgBinaryOp * bin_op = isSgBinaryOp(expr_stmt->get_expression()); SgVarRefExp * var = isSgVarRefExp(bin_op->get_lhs_operand()); if (var == NULL) return; var->get_symbol()->setAttribute("halo_attr", new AstTextAttribute("HALO_VAR")); printf("FortranAnalysis:: adding halo attr to %s\n", var->get_symbol()->get_name().getString().c_str()); } else if (HaloRefSearch::findHaloRef(expr_stmt)) { expr_stmt->setAttribute("halo_ref", new AstTextAttribute("HAS_HALO_REF")); printf("FortranAnalysis:: adding halo attr to statement\n"); } }
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; }
int BasicProgmemTransform::getBuffersizeNeededForFunction(SgFunctionDeclaration *func) { int maxSize = 0; Rose_STL_Container<SgNode *> funcCalls = NodeQuery::querySubTree(func, V_SgFunctionCallExp); for(auto &funcCall: funcCalls) { SgFunctionCallExp *fcall = isSgFunctionCallExp(funcCall); Function callee(fcall); // printf("function called: %s\n", callee.get_name().str()); if(isArduinoProgmemSafeFunction(callee)) { continue; } param_pos_list ignoredPositions = getPositionsToIgnore(callee.get_name().getString()); SgExpressionPtrList params = fcall->get_args()->get_expressions(); int size = 0; for(int pos = 0; pos < params.size(); pos++) { if(ignoredPositions.find(pos) != ignoredPositions.end()) { continue; } SgVarRefExp* var = isSgVarRefExp(params[pos]); if(var) { SgInitializedName *initName = var->get_symbol()->get_declaration(); if(isVarDeclToRemove(initName)) { SgExpression *rhs = getRHSOfVarDecl(initName); if(rhs && isSgStringVal(rhs)) { size += isSgStringVal(rhs)->get_value().size() + 1; } } } } if(size > maxSize) { maxSize = size; } } return maxSize; }
/* * Fix op structure calls and inject debug names */ void OPSource::fixOpFunctions(SgNode *n) { SgName var_name; SgFunctionCallExp *fn = isSgFunctionCallExp(n); if(fn != NULL) { string fn_name = fn->getAssociatedFunctionDeclaration()->get_name().getString(); if(fn_name.compare("op_decl_const")==0) { SgExprListExp* exprList = fn->get_args(); SgExpressionPtrList &exprs = exprList->get_expressions(); if( isSgStringVal(exprs.back()) == NULL ) { SgVarRefExp* varExp = isSgVarRefExp(exprs[1]); if(!varExp) { varExp = isSgVarRefExp(isSgAddressOfOp(exprs[1])->get_operand_i()); } if(varExp) { var_name = varExp->get_symbol()->get_name(); } cout << "---Injecting Debug Name for const: " << var_name.getString() << "---" << endl; exprList->append_expression(buildStringVal(var_name)); } } } }
CPPImperialOpConstDefinition::CPPImperialOpConstDefinition ( SgExprListExp * parameters) { using boost::lexical_cast; using std::string; dimension = isSgIntVal (parameters->get_expressions ()[indexDimenson])->get_value (); SgAddressOfOp * addressOfOperator = isSgAddressOfOp ( parameters->get_expressions ()[indexData]); if (addressOfOperator != NULL) { SgVarRefExp * operandExpression = isSgVarRefExp ( addressOfOperator->get_operand ()); ROSE_ASSERT (operandExpression != NULL); variableName = operandExpression->get_symbol ()->get_name ().getString (); } else { variableName = isSgVarRefExp (parameters->get_expressions ()[indexData])->get_symbol ()->get_name ().getString (); } ROSE_ASSERT (dimension > 0); ROSE_ASSERT (variableName.empty () == false); Debug::getInstance ()->debugMessage ("Found an OP_CONST declaration: '" + variableName + "' Its dimension is " + lexical_cast <string> (dimension), Debug::FUNCTION_LEVEL, __FILE__, __LINE__); }
// 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; }
virtual void visit(SgNode* n) { SgVarRefExp* vr = isSgVarRefExp(n); if (!vr) return; SgInitializedName* in = vr->get_symbol()->get_declaration(); paramMapType::const_iterator iter = paramMap.find(in); if (iter == paramMap.end()) return; // This is not a parameter use vr->set_symbol(iter->second); }
virtual void visit(SgNode* n) { if (isSgBasicBlock(n)) { SgBasicBlock* bb = isSgBasicBlock(n); SgStatementPtrList& stmts = bb->get_statements(); size_t initi; for (size_t decli = 0; decli < stmts.size(); ++decli) { if (isSgVariableDeclaration(stmts[decli])) { SgVariableDeclaration* decl = isSgVariableDeclaration(stmts[decli]); SgInitializedNamePtrList& vars = decl->get_variables(); for (size_t vari = 0; vari != vars.size(); ++vari) { SgInitializedName* in = vars[vari]; if (in->get_initializer() == 0) { bool used = false; for (initi = decli + 1; initi < stmts.size(); used |= containsVariableReference(stmts[initi], in), ++initi) { SgExprStatement* initExprStmt = isSgExprStatement(stmts[initi]); if (initExprStmt) { SgExpression* top = initExprStmt->get_expression(); if (isSgAssignOp(top)) { SgVarRefExp* vr = isSgVarRefExp(isSgAssignOp(top)->get_lhs_operand()); ROSE_ASSERT(isSgAssignOp(top) != NULL); SgExpression* newinit = isSgAssignOp(top)->get_rhs_operand(); if (!used && vr && vr->get_symbol()->get_declaration() == in) { ROSE_ASSERT(newinit != NULL); // printf ("MoveDeclarationsToFirstUseVisitor::visit(): newinit = %p = %s \n",newinit,newinit->class_name().c_str()); ROSE_ASSERT(newinit->get_type() != NULL); SgAssignInitializer* i = new SgAssignInitializer(SgNULL_FILE,newinit,newinit->get_type()); i->set_endOfConstruct(SgNULL_FILE); // printf ("Built a SgAssignInitializer #1 \n"); vars[vari]->set_initializer(i); stmts[initi] = decl; newinit->set_parent(i); // DQ (6/23/2006): Set the parent and file_info pointers // printf ("Setting parent of i = %p = %s to parent = %p = %s \n",i,i->class_name().c_str(),in,in->class_name().c_str()); i->set_parent(in); ROSE_ASSERT(i->get_parent() != NULL); i->set_file_info(new Sg_File_Info(*(newinit->get_file_info()))); ROSE_ASSERT(i->get_file_info() != NULL); // Assumes only one var per declaration FIXME ROSE_ASSERT (vars.size() == 1); stmts.erase(stmts.begin() + decli); --decli; // To counteract ++decli in loop header break; // To get out of initi loop } } } } } } } } } }
// Propagate definitions of a variable to its uses. // Assumptions: var is only assigned at the top level of body // nothing var depends on is assigned within body // Very simple algorithm designed to only handle simplest cases void simpleUndoFiniteDifferencingOne(SgBasicBlock* body, SgExpression* var) { SgExpression* value = 0; SgStatementPtrList& stmts = body->get_statements(); vector<SgStatement*> stmts_to_remove; for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { // cout << "Next statement: value = " << (value ? value->unparseToString() : "(null)") << endl; // cout << (*i)->unparseToString() << endl; if (isSgExprStatement(*i) && isSgAssignOp(isSgExprStatement(*i)->get_expression())) { SgAssignOp* assignment = isSgAssignOp(isSgExprStatement(*i)->get_expression()); // cout << "In assignment statement " << assignment->unparseToString() << endl; if (value) replaceCopiesOfExpression(var, value, assignment->get_rhs_operand()); if (isSgVarRefExp(assignment->get_lhs_operand()) && isSgVarRefExp(var)) { SgVarRefExp* vr = isSgVarRefExp(assignment->get_lhs_operand()); if (vr->get_symbol()->get_declaration() == isSgVarRefExp(var)->get_symbol()->get_declaration()) { value = assignment->get_rhs_operand(); stmts_to_remove.push_back(*i); } } } else { if (value) replaceCopiesOfExpression(var, value, *i); } } for (vector<SgStatement*>::iterator i = stmts_to_remove.begin(); i != stmts_to_remove.end(); ++i) { stmts.erase(std::find(stmts.begin(), stmts.end(), *i)); } if (value) { // DQ (12/17/2006): Separate out the construction of the SgAssignOp from the SgExprStatement to support debugging and testing. // stmts.push_back(new SgExprStatement(SgNULL_FILE, new SgAssignOp(SgNULL_FILE, var, value))); var->set_lvalue(true); SgAssignOp* assignmentOperator = new SgAssignOp(SgNULL_FILE, var, value); var->set_parent(assignmentOperator); value->set_parent(assignmentOperator); printf ("In simpleUndoFiniteDifferencingOne(): assignmentOperator = %p \n",assignmentOperator); // DQ: Note that the parent of the SgExprStatement will be set in AST post-processing (or it should be). SgExprStatement* es = new SgExprStatement(SgNULL_FILE, assignmentOperator); assignmentOperator->set_parent(es); stmts.push_back(es); es->set_parent(body); } }
void HaloRefSearch::visit(SgNode * node) { switch (node->variantT()) { case V_SgVarRefExp: SgVarRefExp * var = isSgVarRefExp(node); if (var->get_symbol()->getAttribute("halo_attr") != NULL) { found = true; } break; } }
foreach(SgAssignOp* op, assigns) { SgVarRefExp* var = isSgVarRefExp(op->get_lhs_operand()); SgInitializedName* decl = var->get_symbol()->get_declaration(); std::cout << "Found assignment to " << var->get_symbol()->get_name().str(); if (decl->get_protected_declaration()) { std::cout << ", which is protected."; } std::cout << "\t\t" << op->unparseToString(); std::cout << std::endl; SgNode* assign_scope = SageInterface::getScope(op); SgNode* var_scope = decl->get_scope(); if (SageInterface::isAncestor(var_scope, assign_scope)) { std::cout << "\tAnd both are in the same scope.\n"; } else { std::cout << "\tIn different scopes.\n"; } }
FortranOpSetDefinition::FortranOpSetDefinition (SgExprListExp * parameters) { /* * ====================================================== * Get name of OP_SET dimension variable * ====================================================== */ if (isSgPntrArrRefExp ( parameters->get_expressions ()[index_setCardinalityName]) != NULL) { dimensionName = isSgPntrArrRefExp ( parameters->get_expressions ()[index_setCardinalityName])->unparseToString (); } else { dimensionName = isSgVarRefExp ( parameters->get_expressions ()[index_setCardinalityName])->get_symbol ()->get_name ().getString (); } /* * ====================================================== * Get name of OP_SET * ====================================================== */ SgVarRefExp * opSetVariableReference; if (isSgDotExp (parameters->get_expressions ()[index_OpSetName]) != NULL) { opSetVariableReference = isSgVarRefExp (isSgDotExp ( parameters->get_expressions ()[index_OpSetName])->get_rhs_operand ()); } else { opSetVariableReference = isSgVarRefExp ( parameters->get_expressions ()[index_OpSetName]); } variableName = opSetVariableReference->get_symbol ()->get_name ().getString (); ROSE_ASSERT (dimensionName.empty () == false); ROSE_ASSERT (variableName.empty () == false); Debug::getInstance ()->debugMessage ("Found an OP_SET definition: '" + variableName + "'. Its dimension is contained in '" + dimensionName + "'", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); }
/* * Create LHS of a loop dependent statement */ void createFirstLoop(SgExprStatement* exprStatement, ArrayAssignmentStatementQueryInheritedAttributeType & arrayAssignmentStatementQueryInheritedData, OperandDataBaseType & operandDataBase) { //transformArrayRefAPP(exprStatement, arrayAssignmentStatementQueryInheritedData, operandDataBase); // Change the LHS, it will the first PntrArrayRef SgScopeStatement* scope = exprStatement->get_scope(); // Figure out the dimensionality of the statement globally vector<SgExpression*> parameters; 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)); } vector<SgVarRefExp*> varRefList = querySubTree<SgVarRefExp> (exprStatement, V_SgVarRefExp); ROSE_ASSERT(varRefList.size() > 0); SgVarRefExp* lhsVarRefExp = (*varRefList.begin()); // LHS should be the first ref SgExpression* replaceExp; if(isFunctionParenthesisOperator(isSgFunctionCallExp(lhsVarRefExp->get_parent()->get_parent()))) { replaceExp = isSgFunctionCallExp(lhsVarRefExp->get_parent()->get_parent()); } else { replaceExp = lhsVarRefExp; } SgVarRefExp* newVarRefExp = buildVarRefExp("__T_pointer", scope); string functionName = "SC_"+lhsVarRefExp->get_symbol()->get_declaration()->get_name(); SgFunctionCallExp* functionCallExp = buildFunctionCallExp(functionName, buildIntType(), buildExprListExp(parameters), scope); SgPntrArrRefExp* pntrArrRefExp2 = buildPntrArrRefExp(newVarRefExp, functionCallExp); ROSE_ASSERT(replaceExp != NULL); replaceExpression(replaceExp, pntrArrRefExp2); return; }
Rose_STL_Container<SgVarRefExp*> buildListOfVariableReferenceExpressionsUsingGlobalVariables ( SgNode* node ) { // This function builds a list of "uses" of variables (SgVarRefExp IR nodes) within the AST. // return variable Rose_STL_Container<SgVarRefExp*> globalVariableUseList; // list of all variables (then select out the global variables by testing the scope) Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree ( node, V_SgVarRefExp ); Rose_STL_Container<SgNode*>::iterator i = nodeList.begin(); while(i != nodeList.end()) { SgVarRefExp *variableReferenceExpression = isSgVarRefExp(*i); assert(variableReferenceExpression != NULL); assert(variableReferenceExpression->get_symbol() != NULL); assert(variableReferenceExpression->get_symbol()->get_declaration() != NULL); assert(variableReferenceExpression->get_symbol()->get_declaration()->get_scope() != NULL); // Note that variableReferenceExpression->get_symbol()->get_declaration() returns the // SgInitializedName (not the SgVariableDeclaration where it was declared)! SgInitializedName* variable = variableReferenceExpression->get_symbol()->get_declaration(); SgScopeStatement* variableScope = variable->get_scope(); // Check if this is a variable declared in global scope, if so, then save it if (isSgGlobal(variableScope) != NULL) { globalVariableUseList.push_back(variableReferenceExpression); } i++; } return globalVariableUseList; }
/********************************************************** * get the InitName for a sgNode *********************************************************/ std::string DefUseAnalysis::getInitName(SgNode* sgNode){ SgInitializedName* initName = NULL; string name = "none"; if (isSgVarRefExp(sgNode)) { SgVarRefExp* varRefExp = isSgVarRefExp(sgNode); initName = varRefExp->get_symbol()->get_declaration(); name = initName->get_qualified_name().str(); } else if (isSgInitializedName(sgNode)) { initName =isSgInitializedName(sgNode); name = initName->get_qualified_name().str(); } else { name = sgNode->class_name(); } return name; }
void FortranAnalysis::visit(SgFunctionCallExp * fcall) { SgFunctionRefExp * fref = isSgFunctionRefExp(fcall->get_function()); if (fref != NULL) { SgExpressionPtrList::iterator it = fcall->get_args()->get_expressions().begin(); std::string name = fref->get_symbol()->get_name().getString(); if (name == "interior" && it != fcall->get_args()->get_expressions().end()) { SgVarRefExp * var = isSgVarRefExp(*it); SgSymbol * sym = var->get_symbol(); sym->setAttribute("halo_attr", new AstTextAttribute("HALO_VAR")); debug("SgFunctionCallExp: adding halo attribute to %s\n", sym->get_name().getString().c_str()); } } }
void BasicProgmemTransform::transformCharArrayInitialization(SgFunctionDeclaration *func) { /* * * Translates statements of the form: * char arr[n] = "some string"; to: * char arr[n]; * strcpy_P(arr, <progmem placeholder>); * */ Rose_STL_Container<SgNode *> initNames = NodeQuery::querySubTree(func, V_SgInitializedName); for(auto &item: initNames) { SgInitializedName *initName = isSgInitializedName(item); if(initName->get_initializer() == NULL) { continue; } SgVariableDeclaration * varDecl = isSgVariableDeclaration(initName->get_declaration()); if(varDecl == NULL) { continue; } SgAssignInitializer *assignInit = isSgAssignInitializer(initName->get_initializer()); if(assignInit == NULL) { continue; } SgType *type = initName->get_type(); SgType *eleType = SageInterface::getElementType(type); if(isSgArrayType(type) && eleType != NULL && isSgTypeChar(eleType)) { SgStringVal* strVal = isSgStringVal(assignInit->get_operand()); std::string str = strVal->get_value(); int arrSize = getDeclaredArraySize(isSgArrayType(type)); if(arrSize == 0) { //char arr[] = "something"; int size = str.length() + 1; SgArrayType *type = SageBuilder::buildArrayType(SageBuilder::buildCharType(), SageBuilder::buildIntVal(size)); initName->set_type(type); } varDecl->reset_initializer(NULL); SgVariableDeclaration *placeholder = getVariableDeclPlaceholderForString(str); SgVarRefExp *ref = SageBuilder::buildVarRefExp(placeholder); std::stringstream instr; instr << "\n strcpy_P(" << initName->get_name().getString(); instr << ", " << ref->get_symbol()->get_name().getString() << ");\n"; SageInterface::attachComment(varDecl, instr.str(), PreprocessingInfo::after); printf("transformed %s\n", initName->unparseToString().c_str()); } } }
bool TaintAnalysis::magic_tainted(SgNode *node, FiniteVarsExprsProductLattice *prodLat) { if (isSgInitializedName(node)) { SgInitializedName *iname = isSgInitializedName(node); std::string vname = iname->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(iname))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVarRefExp(node)) { SgVarRefExp *vref = isSgVarRefExp(node); std::string vname = vref->get_symbol()->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(vref))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVariableDeclaration(node)) { SgVariableDeclaration *vdecl = isSgVariableDeclaration(node); const SgInitializedNamePtrList &inames = vdecl->get_variables(); for (size_t i=0; i<inames.size(); ++i) { std::string vname = inames[i]->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(inames[i]))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } } return false; }
std::set<varID> BasicProgmemTransform::getVarsBoundToNonPlaceholderPointers() { std::set<varID> results; Rose_STL_Container<SgNode *> varRefs = NodeQuery::querySubTree(project, V_SgVarRefExp); for(auto &ref: varRefs) { SgVarRefExp *var = isSgVarRefExp(ref); if(isFromLibrary(var->get_symbol()->get_declaration())){ continue; } varID varRef = SgExpr2Var(var); if(varRef.str().find(STRING_LITERAL_PREFIX) == std::string::npos) { std::set<varID> aliases = aliasAnalysis->getAliasesForVariableAtNode(var, varRef); if(aliases.size() == 0) { aliases.insert(varRef); } results.insert(aliases.begin(), aliases.end()); } } return results; }
bool FortranAnalysis::matchRegionAssignment(SgExprStatement * expr_stmt) { SgBinaryOp * bin_op = isSgBinaryOp(expr_stmt->get_expression()); if (bin_op == NULL) return false; SgFunctionCallExp * fcall = isSgFunctionCallExp(bin_op->get_rhs_operand()); if (fcall == NULL) return false; SgFunctionRefExp * fref = isSgFunctionRefExp(fcall->get_function()); if (fref == NULL) return false; SgExpressionPtrList::iterator it = fcall->get_args()->get_expressions().begin(); std::string name = fref->get_symbol()->get_name().getString(); if (name == "interior" && it != fcall->get_args()->get_expressions().end()) { SgVarRefExp * var = isSgVarRefExp(*it); if (var == NULL) return false; AstTextAttribute * attr = (AstTextAttribute *) var->get_symbol()->getAttribute("dummy_attr"); if (attr == NULL) return false; if (attr->toString() != "DUMMY_ARRAY_ARG") return false; } return true; }
/* * Constructor for registering an expression. */ RegisterPointers::RegisterPointers(SgExpression* p_expression) : expression(p_expression), varName(NULL), varSymbol(NULL), isGlobal(false), definedInSystemHeader(false), compilerGenerated(false), addrUsedInIO(false) { //TODO maybe need to do a while loop until we get a var ref? ROSE_ASSERT(isSgPointerType(expression->get_type())); SgAddressOfOp* addrOf = isSgAddressOfOp(expression); if(addrOf) { //Check to make sure we don't register vars the compiler added SgVarRefExp* varRef = isSgVarRefExp(addrOf->get_operand()); if(varRef) { varSymbol = varRef->get_symbol(); compilerGenerated = isCompilerGenerated(varSymbol); addrUsedInIO = isAddrTakenInIrrelevantFunc(varRef); } } }
void testOMPForSensitiveInsertion() { annotateAllOmpFors(project); Rose_STL_Container<SgNode*> iteratorUses = NodeQuery::querySubTree(project, V_SgInitializedName); OMPcfgRWTransaction trans; //VirtualCFG::cfgRWTransaction trans; trans.beginTransaction(); for(Rose_STL_Container<SgNode*>::iterator it = iteratorUses.begin(); it!=iteratorUses.end(); it++) { SgInitializedName *initName = isSgInitializedName(*it); ROSE_ASSERT(initName); //printf("initialized Name <%s | %s>\n", initName->get_parent()->unparseToString().c_str(), initName->get_parent()->class_name().c_str()); if(initName->get_name().getString() == "iterator") { //printf(" inserting1 at spot <%s | %s>\n", initName->get_parent()->unparseToString().c_str(), initName->get_parent()->class_name().c_str()); trans.insertBefore(initName, fooCallCreate()); trans.insertAfter(initName, fooCallCreate()); } } iteratorUses = NodeQuery::querySubTree(project, V_SgVarRefExp); for(Rose_STL_Container<SgNode*>::iterator it = iteratorUses.begin(); it!=iteratorUses.end(); it++) { SgVarRefExp *varRef = isSgVarRefExp(*it); ROSE_ASSERT(varRef); if(varRef->get_symbol()->get_name().getString() == "iterator") { //printf(" inserting2 at spot <%s | %s>\n", varRef->get_parent()->unparseToString().c_str(), varRef->get_parent()->class_name().c_str()); trans.insertBefore(varRef->get_parent(), fooCallCreate()); trans.insertAfter(varRef->get_parent(), fooCallCreate()); } } trans.commitTransaction(); }
DataDependenceGraph::DataDependenceGraph(SgNode * head,EDefUse * du, InterproceduralInfo * ii):_head(isSgFunctionDefinition (head)) { defuse=du; #else DataDependenceGraph::DataDependenceGraph(SgNode * head, InterproceduralInfo * ii):_head(isSgFunctionDefinition (head)) { _buildDefUseChains(_head); #endif _interprocedural = ii; functionDef=isSgFunctionDefinition(head); functionDecl=functionDef->get_declaration(); buildDDG(); } void outputNodeInfo(std::ostream & os,SgNode* defSgNode) { if (isSgInitializedName(defSgNode)!=NULL) { os <<"\""<<isSgInitializedName(defSgNode)->get_qualified_name().getString()<<"\" of class "<<defSgNode->class_name(); } else { os <<"\""<<defSgNode->unparseToString()<<"\" of class "<<defSgNode->class_name(); } } //construct the data dependence graph void DataDependenceGraph::buildDDG() { //for debugging purposes, print out the def and use maps //defuse->printDefUse(); //iterate over all variable references in the function DependenceNode *defDepNode=NULL; DependenceNode *useDepNode=NULL; // this graph is intersted of all ueses of variables, up so far NO POINTER analysis is done... Rose_STL_Container< SgNode * > varUse=NodeQuery::querySubTree(_head,V_SgVarRefExp); for (Rose_STL_Container< SgNode * >::iterator i = varUse.begin();i!=varUse.end();i++) { // if the variable is a global, special treatmen SgVarRefExp * varRef = isSgVarRefExp(*i); SgNode * varDef; SgNode * interestingUseParent, * interestingDefParent; // get the correct interesting node for the use // uw-mist TODO: rewrite the getnextparent interestingUseParent=getNextParentInterstingNode(varRef); //Now, grab the proper use node in the system dependence graph, or create it if it doesn't exist //uw-mist replaced the call //if (isSgFunctionCallExp(getNextParentInterstingNode(interestingUseParent->get_parent()))) if (isSgFunctionCallExp(interestingUseParent)) { // check if the variable is used as argument in a function call (special case in system dependence graph) useDepNode=getNode(DependenceNode::ACTUALIN,varRef); } else if (isSgFunctionDefinition(interestingUseParent)) { continue; } else { useDepNode=getNode(interestingUseParent); } // the current node is defined, next get the defining nodes //Jim: What's the point of jumping straight to the decleration here? //We should want the def. from the defuse chains... std::vector< SgNode* > defPlaces,usePlaces; SgInitializedName *initName=varRef->get_symbol()->get_declaration(); //VERBOSE_DEBUG_STMT(std::string varName=initName->get_name().getString();) // handle global variable definition if (defuse->isNodeGlobalVariable(initName)) { // initName->get_declaration (); // the variable is a global variable, now connect the statement with the global def if (DUVariableAnalysisExt::isIDef(varRef) || DUVariableAnalysisExt::isDef(varRef)) { // create a ade from the ref to the globalInitialisation establishEdge(useDepNode,getNode(initName->get_declaration()),GLOBALVAR_HELPER); } if (DUVariableAnalysisExt::isIUse(varRef) || DUVariableAnalysisExt::isUse(varRef)) { // create a ade from the ref to the globalInitialisation establishEdge(getNode(initName->get_declaration()),useDepNode,GLOBALVAR_HELPER); } } //Main Case: Variable Use // if the current use of the variable is a use if (DUVariableAnalysisExt::isUse(varRef) || DUVariableAnalysisExt::isIUse(varRef)) { //Jim: Debug lines, just uncommented //cout <<"initname: 2: intersetingUseParent for "<< initName->get_name().getString() << // " is "<<interestingUseParent->unparseToString()<<" and is of type "<<interestingUseParent->class_name()<<endl; //VERBOSE_DEBUG_BLOCK(std::cout<<"\tUSE"<<endl;) // get definition places for the interesting node //Jim: this appears to be dead code //defPlaces=defuse->getDefFor(interestingUseParent,initName); //Does the below not over write the above? Curious. Removing the below creates a false self-ref link on x+=5; defPlaces=defuse->getDefFor(varRef,initName); // for all possible definition places for (unsigned int j=0;j<defPlaces.size();j++) { // get the def, so we don't have to use the array all the time varDef=defPlaces[j]; // make sure it is the interesting def parent interestingDefParent=getNextParentInterstingNode(varDef); defDepNode=NULL; // if the next interesting node is a function call, this definition comes from a ACTUAL_OUT if (isSgFunctionCallExp(getNextParentInterstingNode(interestingDefParent->get_parent())) || isSgFunctionCallExp(getNextParentInterstingNode(interestingDefParent)) || isSgFunctionCallExp(interestingDefParent) || isSgFunctionCallExp(interestingDefParent->get_parent()) || isSgFunctionCallExp(interestingDefParent->get_parent()->get_parent()) ) { //establish edge from function call to actual out defDepNode=getNode(DependenceNode::ACTUALOUT,interestingDefParent); establishEdge(defDepNode,useDepNode,DATA); // if the next node is a function definition } else if (isSgFunctionDefinition(interestingDefParent)) { //connect edge from function definition to formal in defDepNode=getNode(DependenceNode::FORMALIN,interestingDefParent); establishEdge(defDepNode,useDepNode,DATA); } // if the next node is a function parameter arg list else if (isSgFunctionParameterList(interestingDefParent->get_parent())) { //connect the function args to the formal in nodes defDepNode=getNode(DependenceNode::FORMALIN,interestingDefParent); establishEdge(defDepNode,useDepNode,DATA); } else { //assume a general data edge defDepNode=getNode(interestingDefParent); establishEdge(defDepNode,useDepNode,DATA); } } } //NOW SWITCH from wanting Uses to Defs: //Additional Dependence Graph Initialization: //connect formal in defs to variable uses if (DUVariableAnalysisExt::isIDef(varRef)) { // cout <<"\tIUSE"<<endl; // cout <<"\tIDEF"<<endl; defPlaces=defuse->getDefFor(varRef,initName); for (unsigned int j=0;j<defPlaces.size();j++) { // cout<<"\tdef "<<j<<": "<<defPlaces[j]->unparseToString()<<endl; // cout<<"\tclass:"<<defPlaces[j]->class_name()<<endl; interestingDefParent=getNextParentInterstingNode(defPlaces[j]); if (isSgFunctionParameterList(interestingDefParent) || isSgFunctionParameterList(interestingDefParent) || isSgFunctionParameterList(defPlaces[j]->get_parent()) && isSgFunctionDeclaration(defPlaces[j]->get_parent()->get_parent())) { defDepNode=getNode(DependenceNode::FORMALIN,defPlaces[j]); } else { defDepNode=getNode(interestingDefParent); } establishEdge(defDepNode,useDepNode,DATA); } } } //END OF MAIN VARIABLE LOOP //FINAL DEPENDENCE GRAPH STEPS: //uw-mist //begin by connecting all ActualOut nodes to the function args //start by getting all callsites representing a function for (int i=0;i<_interprocedural->callSiteCount();i++) { //for this individual function, visit each arg for (int j=0;j<_interprocedural->getActualInCount(i);j++) { SgNode * actOut = _interprocedural->getActualIn(i,j); //if it is not a reference expression, search to find the lower reference expressions in the complex arg //uw-mist TODO: (If neccessary) for now, just skip if(!isSgVarRefExp(actOut)) continue; //search the def/use map SgInitializedName *actOutInitName=isSgVarRefExp(actOut)->get_symbol()->get_declaration(); DependenceNode * actOutDep = getNode(DependenceNode::ACTUALOUT,actOut); //connect to all potential definitions (not as exact as possible, but should work for first pass //uw-mist TODO: connect directly to all potential use paths instead std::vector< SgNode* > defPlaces=defuse->getDefFor(actOut,actOutInitName); for (unsigned int k=0;k<defPlaces.size();k++) { establishEdge(actOutDep,getNode(getNextParentInterstingNode(defPlaces[k])),DATA); } } } // force a dependence from the ACTUALOUT to the Functionscall // iterate over all function-calls to connect the actual in/out edges Rose_STL_Container< SgNode * > functionCall=NodeQuery::querySubTree(_head,V_SgFunctionCallExp); for (Rose_STL_Container< SgNode * >::iterator call=functionCall.begin(); call != functionCall.end();call++) { // track down the parent imporant node to establish a data-dependency DependenceNode * callDepNode,*returnNode; // actualreturn returnNode=getNode(DependenceNode::ACTUALRETURN,*call); SgNode* callTmp=(*call)->get_parent(); // if the paren is the interesting node or a call break while(!IsImportantForSliceSgFilter(callTmp) && !isSgFunctionCallExp(callTmp)) { callTmp=callTmp->get_parent(); } // returnvalue is used in a function call, connect if (isSgFunctionCallExp(callTmp)) { // get the actual in SgNode *paramFindTmp=*call; while(!isSgExprListExp(paramFindTmp->get_parent())) { paramFindTmp=paramFindTmp->get_parent(); } // paramFindTmp is now the parameter of the function call callDepNode=getNode(DependenceNode::ACTUALIN,paramFindTmp); } else { callDepNode=getNode(callTmp); } assert(returnNode!=NULL); assert(callDepNode!=NULL); establishEdge(returnNode,callDepNode,DATA); } //Now connect return statements: //first, build up list of return statements Rose_STL_Container< SgNode * >returnStmts = NodeQuery::querySubTree(_head,V_SgReturnStmt); // if the last stmnt is not a return stmt, add that statement to the list, such that any modified formal_in parameters are linked correctly if (_head->get_body ()->get_statements ().size() && !isSgReturnStmt(*(_head->get_body ()->get_statements ().rbegin()))) { // cout <<"last stmt is "<<(*(_head->get_body ()->get_statements ().rbegin()))->unparseToString()<<endl; // cout <<"last stmt is "<<_head->get_body ()->unparseToString()<<endl; // cout <<"cfg says: "<<_head->get_declaration()->cfgForEnd ().getNode()->unparseToString()<<" is the end"<<endl; // returnStmts.push_back(_head->get_declaration()->cfgForEnd ().getNode()); // the last stmt might be a def, take the body as the sink for the CFG // returnStmts.push_back(_head->get_body ()); returnStmts.push_back(_head); // returnStmts.push_back(*(_head->get_body ()->get_statements ().rbegin())); } // process return statements for (Rose_STL_Container< SgNode * >::iterator returnS=returnStmts.begin(); returnS != returnStmts.end();returnS++) { SgNode * stmt=*returnS; // cout <<"processing end-stantement: "<<stmt->unparseToString()<<endl; // if the return statement has actually some return values, connect those to the formal out if (isSgReturnStmt(stmt) /*&& isSgReturnStmt(stmt)->get_expression ()!=NULL*/) { // cout <<"is return,creating out edge"<<endl; // check if the sub-expression of the return contains any function calls for wich we have to create data-dependencys .. later Rose_STL_Container< SgNode * > returnRefs=NodeQuery::querySubTree(stmt,V_SgVarRefExp); for (Rose_STL_Container<SgNode*>::iterator refIt=returnRefs.begin();refIt!=returnRefs.end();refIt++) { establishEdge( getNode(getNextParentInterstingNode(*refIt)), getNode(DependenceNode::FORMALRETURN,_head->get_declaration()), DATA); // if this varaible is not from the initial name list } //SgVarRefExp * varRef=isSgVarRefExp(*i); } } // since not all functionparameters may be requried for this function, but the stack has to be valid, force a data depenancy form the fucntion enrty to the formal in std::set<SgInitializedName*> functionParameterSet(_head->get_declaration()->get_args().begin(),_head->get_declaration()->get_args().end()); for (std::set<SgInitializedName*>::iterator param=functionParameterSet.begin();param!=functionParameterSet.end();param++) { // cout <<"adding backedge for slicing purpose"<<endl; establishEdge( getNode(DependenceNode::FORMALIN,*param), getNode(DependenceNode::ENTRY,functionDef), COMPLETENESS_HELPER); }; }
void generateStencilCode(StencilEvaluationTraversal & traversal, bool generateLowlevelCode) { // Read the stencil and generate the inner most loop AST for the stencil. // Note that generateLowlevelCode controls the generation of low level C code using a // base pointer to raw memory and linearized indexing off of that pointer. The // alternative is to use the operator[] member function in the RectMDArray class. // Example of code that we want to generate: // for (j=0; j < source.size(0); j++) // { // int axis_x_size = source.size(0); // for (i=0; i < source.size(0); i++) // { // destination[j*axis_x_size+i] = source[j*axis_x_size+i]; // } // } // This function genertes the loop nest only: // SgForStatement* buildLoopNest(int stencilDimension, SgBasicBlock* & innerLoopBody) // This function generates the statement in the inner most loop body: // SgExprStatement* assembleStencilSubTreeArray(vector<SgExpression*> & stencilSubTreeArray) // This function generates the AST representing the stencil points: // SgExpression* buildStencilPoint (StencilOffsetFSM* stencilOffsetFSM, double stencilCoeficient, int stencilDimension, SgVariableSymbol* destinationVariableSymbol, SgVariableSymbol* sourceVariableSymbol) // The generated code should be in terms of the operator[]() functions on the // RectMDArray objects. Likely we have to support a wider range of generated code later. // const RectMDArray<TDest>& a_LOfPhi, // const RectMDArray<TSrc>& a_phi, // std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList; std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList = traversal.get_stencilOperatorFunctionCallList(); for (size_t i = 0; i < stencilOperatorFunctionCallList.size(); i++) { SgFunctionCallExp* functionCallExp = stencilOperatorFunctionCallList[i]; ROSE_ASSERT(functionCallExp != NULL); printf ("processing functionCallExp = %p \n",functionCallExp); SgStatement* associatedStatement = TransformationSupport::getStatement(functionCallExp); ROSE_ASSERT(associatedStatement != NULL); string filename = associatedStatement->get_file_info()->get_filename(); int lineNumber = associatedStatement->get_file_info()->get_line(); printf ("Generating code for stencil operator used at file = %s at line = %d \n",filename.c_str(),lineNumber); SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // There should be four elements to a stencil operator. ROSE_ASSERT(argumentList->get_expressions().size() == 4); // Stencil SgExpression* stencilExpression = argumentList->get_expressions()[0]; SgVarRefExp* stencilVarRefExp = isSgVarRefExp(stencilExpression); ROSE_ASSERT(stencilVarRefExp != NULL); // RectMDArray (destination) SgExpression* destinationArrayReferenceExpression = argumentList->get_expressions()[1]; SgVarRefExp* destinationArrayVarRefExp = isSgVarRefExp(destinationArrayReferenceExpression); ROSE_ASSERT(destinationArrayVarRefExp != NULL); // RectMDArray (source) SgExpression* sourceArrayReferenceExpression = argumentList->get_expressions()[2]; SgVarRefExp* sourceArrayVarRefExp = isSgVarRefExp(sourceArrayReferenceExpression); ROSE_ASSERT(sourceArrayVarRefExp != NULL); // Box SgExpression* boxReferenceExpression = argumentList->get_expressions()[3]; SgVarRefExp* boxVarRefExp = isSgVarRefExp(boxReferenceExpression); ROSE_ASSERT(boxVarRefExp != NULL); printf ("DONE: processing inputs to stencil operator \n"); ROSE_ASSERT(stencilVarRefExp->get_symbol() != NULL); SgInitializedName* stencilInitializedName = stencilVarRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(stencilInitializedName != NULL); string stencilName = stencilInitializedName->get_name(); printf ("stencilName = %s \n",stencilName.c_str()); std::map<std::string,StencilFSM*> & stencilMap = traversal.get_stencilMap(); ROSE_ASSERT(stencilMap.find(stencilName) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[stencilName]; ROSE_ASSERT(stencilFSM != NULL); // DQ (2/8/2015): Moved out of loop. int stencilDimension = stencilFSM->stencilDimension(); ROSE_ASSERT(stencilDimension > 0); // These are computed values. printf ("Stencil dimension = %d \n",stencilDimension); printf ("Stencil width = %d \n",stencilFSM->stencilWidth()); std::vector<std::pair<StencilOffsetFSM,double> > & stencilPointList = stencilFSM->stencilPointList; // This is the scope where the stencil operator is evaluated. SgScopeStatement* outerScope = associatedStatement->get_scope(); ROSE_ASSERT(outerScope != NULL); SgVariableSymbol* indexVariableSymbol_X = NULL; SgVariableSymbol* indexVariableSymbol_Y = NULL; SgVariableSymbol* indexVariableSymbol_Z = NULL; SgVariableSymbol* arraySizeVariableSymbol_X = NULL; SgVariableSymbol* arraySizeVariableSymbol_Y = NULL; SgVariableSymbol* destinationVariableSymbol = destinationArrayVarRefExp->get_symbol(); ROSE_ASSERT(destinationVariableSymbol != NULL); SgVariableSymbol* sourceVariableSymbol = sourceArrayVarRefExp->get_symbol(); ROSE_ASSERT(sourceVariableSymbol != NULL); SgVariableSymbol* boxVariableSymbol = boxVarRefExp->get_symbol(); ROSE_ASSERT(boxVariableSymbol != NULL); // This can be important in handling of comments and CPP directives. bool autoMovePreprocessingInfo = true; SgStatement* lastStatement = associatedStatement; if (generateLowlevelCode == true) { #if 1 SgVariableDeclaration* sourceDataPointerVariableDeclaration = buildDataPointer("sourceDataPointer",sourceVariableSymbol,outerScope); #else // Optionally build a pointer variable so that we can optionally support a C style indexing for the DTEC DSL blocks. SgExpression* sourcePointerExp = buildMemberFunctionCall(sourceVariableSymbol,"getPointer",NULL,false); ROSE_ASSERT(sourcePointerExp != NULL); SgAssignInitializer* assignInitializer = SageBuilder::buildAssignInitializer_nfi(sourcePointerExp); ROSE_ASSERT(assignInitializer != NULL); // Build the variable declaration for the pointer to the data. string sourcePointerName = "sourceDataPointer"; SgVariableDeclaration* sourceDataPointerVariableDeclaration = SageBuilder::buildVariableDeclaration_nfi(sourcePointerName,SageBuilder::buildPointerType(SageBuilder::buildDoubleType()),assignInitializer,outerScope); ROSE_ASSERT(sourceDataPointerVariableDeclaration != NULL); #endif // SageInterface::insertStatementAfter(associatedStatement,forStatementScope,autoMovePreprocessingInfo); SageInterface::insertStatementAfter(associatedStatement,sourceDataPointerVariableDeclaration,autoMovePreprocessingInfo); SgVariableDeclaration* destinationDataPointerVariableDeclaration = buildDataPointer("destinationDataPointer",destinationVariableSymbol,outerScope); SageInterface::insertStatementAfter(sourceDataPointerVariableDeclaration,destinationDataPointerVariableDeclaration,autoMovePreprocessingInfo); // Reset the variable symbols we will use in the buildStencilPoint() function. sourceVariableSymbol = SageInterface::getFirstVarSym(sourceDataPointerVariableDeclaration); destinationVariableSymbol = SageInterface::getFirstVarSym(destinationDataPointerVariableDeclaration); lastStatement = destinationDataPointerVariableDeclaration; } SgBasicBlock* innerLoopBody = NULL; // SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,sourceVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,boxVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); ROSE_ASSERT(innerLoopBody != NULL); ROSE_ASSERT(lastStatement != NULL); SageInterface::insertStatementAfter(lastStatement,loopNest,autoMovePreprocessingInfo); // Mark this as compiler generated so that it will not be unparsed. associatedStatement->get_file_info()->setCompilerGenerated(); // Form an array of AST subtrees to represent the different points in the stencil. // vector<SgFunctionCallExp*> stencilSubTreeArray; vector<SgExpression*> stencilSubTreeArray; for (size_t j = 0; j < stencilPointList.size(); j++) { #if 0 printf ("Forming stencil point subtree for offsetValues[0] = %3d [1] = %3d [2] = %3d \n",stencilPointList[j].first.offsetValues[0],stencilPointList[j].first.offsetValues[1],stencilPointList[j].first.offsetValues[2]); #endif StencilOffsetFSM* stencilOffsetFSM = &(stencilPointList[j].first); double stencilCoeficient = stencilPointList[j].second; // SgFunctionCallExp* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilFSM->stencilDimension()); SgExpression* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilDimension,sourceVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencilSubTree != NULL); stencilSubTreeArray.push_back(stencilSubTree); } // Construct the lhs value for the stencil inner loop statement. StencilOffsetFSM* stencilOffsetFSM_lhs = new StencilOffsetFSM(0,0,0); double stencilCoeficient_lhs = 1.00; SgExpression* stencil_lhs = buildStencilPoint(stencilOffsetFSM_lhs,stencilCoeficient_lhs,stencilDimension,destinationVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencil_lhs != NULL); // Assemble the stencilSubTreeArray into a single expression. SgExprStatement* stencilStatement = assembleStencilSubTreeArray(stencil_lhs,stencilSubTreeArray,stencilDimension,destinationVariableSymbol); SageInterface::appendStatement(stencilStatement,innerLoopBody); } }
DOTSynthesizedAttribute AstDOTGeneration::evaluateSynthesizedAttribute(SgNode* node, DOTInheritedAttribute ia, SubTreeSynthesizedAttributes l) { SubTreeSynthesizedAttributes::iterator iter; ROSE_ASSERT(node); // printf ("AstDOTGeneration::evaluateSynthesizedAttribute(): node = %s \n",node->class_name().c_str()); // DQ (5/3/2006): Skip this IR node if it is specified as such in the inherited attribute if (ia.skipSubTree == true) { // I am unclear if I should return NULL or node as a parameter to DOTSynthesizedAttribute // Figured this out: if we return a valid pointer then we get a node in the DOT graph // (with just the pointer value as a label), where as if we return a DOTSynthesizedAttribute // with a NUL pointer then the node will NOT appear in the DOT graph. // return DOTSynthesizedAttribute(node); return DOTSynthesizedAttribute(NULL); } string nodeoption; if(AstTests::isProblematic(node)) { // cout << "problematic node found." << endl; nodeoption="color=\"orange\" "; } string nodelabel=string("\\n")+node->class_name(); // DQ (1/24/2009): Added support for output of isForward flag in the dot graph. SgDeclarationStatement* genericDeclaration = isSgDeclarationStatement(node); if (genericDeclaration != NULL) { // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. string name = (genericDeclaration->isForward() == true) ? "isForward" : "!isForward"; ROSE_ASSERT(name.empty() == false); // DQ (3/20/2011): Added class names to the generated dot file graphs of the AST. SgClassDeclaration* classDeclaration = isSgClassDeclaration(genericDeclaration); if (classDeclaration != NULL) { nodelabel += string("\\n") + classDeclaration->get_name(); } // DQ (3/20/2011): Added function names to the generated dot file graphs of the AST. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(genericDeclaration); if (functionDeclaration != NULL) { nodelabel += string("\\n") + functionDeclaration->get_name(); } nodelabel += string("\\n") + name; } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgInitializedName* initializedName = isSgInitializedName(node); if (initializedName != NULL) { nodelabel += string("\\n") + initializedName->get_name(); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgIntVal* intValue = isSgIntVal(node); if (intValue != NULL) { nodelabel += string("\\n value = ") + StringUtility::numberToString(intValue->get_value()); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgVarRefExp* varRefExp = isSgVarRefExp(node); if (varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); string name = variableSymbol->get_name(); nodelabel += string("\\n name = ") + name; } // DQ (1/19/2009): Added support for output of what specific instrcution this is in the dot graph. SgAsmInstruction* genericInstruction = isSgAsmInstruction(node); if (genericInstruction != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. #if 1 string unparsedInstruction = unparseInstruction(genericInstruction); string addressString = StringUtility::numberToString( (void*) genericInstruction->get_address() ); // string name = genericInstruction->get_mnemonic(); string name = unparsedInstruction + "\\n address: " + addressString; #else string name = unparsedInstruction + "\\n" + addressString; #endif ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } SgAsmExpression* genericExpression = isSgAsmExpression(node); if (genericExpression != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT string name = unparseExpression(genericExpression, NULL, NULL); ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (10/29/2008): Added some support for additional output of internal names for specific IR nodes. // In generall there are long list of these IR nodes in the binary and this helps make some sense of // the lists (sections, symbols, etc.). SgAsmExecutableFileFormat* binaryFileFormatNode = isSgAsmExecutableFileFormat(node); if (binaryFileFormatNode != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // The case of binary file format IR nodes can be especially confusing so we want the // default to output some more specific information for some IR nodes (e.g. sections). string name; SgAsmGenericSection* genericSection = isSgAsmGenericSection(node); if (genericSection != NULL) { SgAsmGenericString* genericString = genericSection->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmGenericSymbol* genericSymbol = isSgAsmGenericSymbol(node); if (genericSymbol != NULL) { SgAsmGenericString* genericString = genericSymbol->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); if (name.empty() == true) name = "no_name_for_symbol"; } SgAsmGenericDLL* genericDLL = isSgAsmGenericDLL(node); if (genericDLL != NULL) { SgAsmGenericString* genericString = genericDLL->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmPEImportItem* peImportItem = isSgAsmPEImportItem(node); if (peImportItem != NULL) { SgAsmGenericString* genericString = peImportItem->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmDwarfLine* asmDwarfLine = isSgAsmDwarfLine(node); if (asmDwarfLine != NULL) { char buffer[100]; // It does not work to embed the "\n" into the single sprintf parameter. // sprintf(buffer," Addr: 0x%08"PRIx64" \n line: %d col: %d ",asmDwarfLine->get_address(),asmDwarfLine->get_line(),asmDwarfLine->get_column()); sprintf(buffer,"Addr: 0x%08"PRIx64,asmDwarfLine->get_address()); name = buffer; sprintf(buffer,"line: %d col: %d",asmDwarfLine->get_line(),asmDwarfLine->get_column()); name += string("\\n") + buffer; } SgAsmDwarfConstruct* asmDwarfConstruct = isSgAsmDwarfConstruct(node); if (asmDwarfConstruct != NULL) { name = asmDwarfConstruct->get_name(); } #if 0 // This might not be the best way to implement this, since we want to detect common base classes of IR nodes. switch (node->variantT()) { case V_SgAsmElfSection: { SgAsmElfSection* n = isSgAsmElfSection(node); name = n->get_name(); break; } default: { // No additional information is suggested for the default case! } } #endif if (name.empty() == false) nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (11/29/2008): Output the directives in the label of the IR node. SgC_PreprocessorDirectiveStatement* preprocessorDirective = isSgC_PreprocessorDirectiveStatement(node); if (preprocessorDirective != NULL) { string s = preprocessorDirective->get_directiveString(); // Change any double quotes to single quotes so that DOT will not misunderstand the generated lables. while (s.find("\"") != string::npos) { s.replace(s.find("\""),1,"\'"); } if (s.empty() == false) nodelabel += string("\\n") + s; } nodelabel += additionalNodeInfo(node); // DQ (11/1/2003) added mechanism to add additional options (to add color, etc.) // nodeoption += additionalNodeOptions(node); string additionalOptions = additionalNodeOptions(node); // printf ("nodeoption = %s size() = %ld \n",nodeoption.c_str(),nodeoption.size()); // printf ("additionalOptions = %s size() = %ld \n",additionalOptions.c_str(),additionalOptions.size()); string x; string y; x += additionalOptions; nodeoption += additionalOptions; DOTSynthesizedAttribute d(0); // DQ (7/27/2008): Added mechanism to support pruning of AST bool commentoutNode = commentOutNodeInGraph(node); if (commentoutNode == true) { // DQ (11/10/2008): Fixed to only output message when (verbose_level > 0); command-line option. // DQ (7/27/2008): For now just return to test this mechanism, then we want to add comment "//" propoerly to generated DOT file. if (SgProject::get_verbose() > 0) { printf ("Skipping the use of this IR node in the DOT Graph \n"); } } else { // ************************** switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(ia.tdbuTracePos,tdbuTrace)+nodelabel,nodeoption); break; case PREORDER: case TOPDOWN: dotrep.addNode(node,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); break; case POSTORDER: case BOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(buTrace)+nodelabel,nodeoption); break; default: assert(false); } ++tdbuTrace; ++buTrace; // add edges or null values int testnum=0; for (iter = l.begin(); iter != l.end(); iter++) { string edgelabel = string(node->get_traversalSuccessorNamesContainer()[testnum]); string toErasePrefix = "p_"; if (AstTests::isPrefix(toErasePrefix,edgelabel)) { edgelabel.erase(0, toErasePrefix.size()); } if ( iter->node == NULL) { // SgNode* snode=node->get_traversalSuccessorContainer()[testnum]; AstSuccessorsSelectors::SuccessorsContainer c; AstSuccessorsSelectors::selectDefaultSuccessors(node,c); SgNode* snode=c[testnum]; // isDefault shows that the default constructor for synth attribute was used if (l[testnum].isDefault() && snode && (visitedNodes.find(snode) != visitedNodes.end()) ) { // handle bugs in SAGE dotrep.addEdge(node,edgelabel,snode,"dir=forward arrowhead=\"odot\" color=red "); } else { if (snode == NULL) { dotrep.addNullValue(node,"",edgelabel,""); } } } else { // DQ (3/5/2007) added mechanism to add additional options (to add color, etc.) string edgeoption = additionalEdgeOptions(node,iter->node,edgelabel); switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=both"); break; case PREORDER: case TOPDOWN: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=forward"); break; case POSTORDER: case BOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=back"); break; default: assert(false); } } testnum++; } // ************************** } // DQ (7/4/2008): Support for edges specified in AST attributes AstAttributeMechanism* astAttributeContainer = node->get_attributeMechanism(); if (astAttributeContainer != NULL) { // Loop over all the attributes at this IR node for (AstAttributeMechanism::iterator i = astAttributeContainer->begin(); i != astAttributeContainer->end(); i++) { // std::string name = i->first; AstAttribute* attribute = i->second; ROSE_ASSERT(attribute != NULL); // This can return a non-empty list in user-defined attributes (derived from AstAttribute). // printf ("Calling attribute->additionalNodeInfo() \n"); std::vector<AstAttribute::AttributeNodeInfo> nodeList = attribute->additionalNodeInfo(); // printf ("nodeList.size() = %lu \n",nodeList.size()); for (std::vector<AstAttribute::AttributeNodeInfo>::iterator i_node = nodeList.begin(); i_node != nodeList.end(); i_node++) { SgNode* nodePtr = i_node->nodePtr; string nodelabel = i_node->label; string nodeoption = i_node->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding a node nodelabel = %s nodeoption = %s \n",nodelabel.c_str(),nodeoption.c_str()); // dotrep.addNode(NULL,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); dotrep.addNode( nodePtr, dotrep.traceFormat(ia.tdTracePos) + nodelabel, nodeoption ); } // printf ("Calling attribute->additionalEdgeInfo() \n"); std::vector<AstAttribute::AttributeEdgeInfo> edgeList = attribute->additionalEdgeInfo(); // printf ("edgeList.size() = %lu \n",edgeList.size()); for (std::vector<AstAttribute::AttributeEdgeInfo>::iterator i_edge = edgeList.begin(); i_edge != edgeList.end(); i_edge++) { string edgelabel = i_edge->label; string edgeoption = i_edge->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding an edge from i_edge->fromNode = %p to i_edge->toNode = %p edgelabel = %s edgeoption = %s \n",i_edge->fromNode,i_edge->toNode,edgelabel.c_str(),edgeoption.c_str()); dotrep.addEdge(i_edge->fromNode,edgelabel,i_edge->toNode,edgeoption + "dir=forward"); } } } switch(node->variantT()) { // DQ (9/1/2008): Added case for output of SgProject rooted DOT file. // This allows source code and binary files to be combined into the same DOT file. case V_SgProject: { SgProject* project = dynamic_cast<SgProject*>(node); ROSE_ASSERT(project != NULL); string generatedProjectName = SageInterface::generateProjectName( project ); // printf ("generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); if (generatedProjectName.length() > 40) { // printf ("Warning: generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); generatedProjectName = "aggregatedFileNameTooLong"; printf ("Proposed (generated) filename is too long, shortened to: %s \n",generatedProjectName.c_str()); } string filename = string("./") + generatedProjectName + ".dot"; // printf ("generated filename for dot file (from SgProject) = %s \n",filename.c_str()); if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgProject IR node (filename = %s) \n",filename.c_str()); dotrep.writeToFileAsGraph(filename); break; } // case V_SgFile: case V_SgSourceFile: case V_SgBinaryComposite: { SgFile* file = dynamic_cast<SgFile*>(node); ROSE_ASSERT(file != NULL); string original_filename = file->getFileName(); // DQ (7/4/2008): Fix filenamePostfix to go before the "." // string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + "."+filenamePostfix+"dot"; string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + filenamePostfix + ".dot"; // printf ("generated filename for dot file (from SgSourceFile or SgBinaryComposite) = %s file->get_parent() = %p \n",filename.c_str(),file->get_parent()); // printf ("file->get_parent() = %p \n",file->get_parent()); // cout << "generating DOT file (from SgSourceFile or SgBinaryComposite): " << filename2 << " ... "; // DQ (9/1/2008): this effects the output of DOT files when multiple files are specified // on the command line. A SgProject is still built even when a single file is specificed // on the command line, however there are cases where a SgFile can be built without a // SgProject and this case allows those SgFile rooted subtrees to be output as DOT files. // If there is a SgProject then output the dot file from there, else output as a SgFile. if (file->get_parent() == NULL) { // If there is no SgProject then output the file now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (no SgProject available) \n"); dotrep.writeToFileAsGraph(filename); } else { // There is a SgProject IR node, but if we will be traversing it we want to output the // graph then (so that the graph will include the SgProject IR nodes and connect multiple // files (SgSourceFile or SgBinaryComposite IR nodes). if ( visitedNodes.find(file->get_parent()) == visitedNodes.end() ) { // This SgProject node was not input as part of the traversal, // so we will not be traversing the SgProject IR nodes and we // have to output the graph now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (SgProject was not traversed) \n"); dotrep.writeToFileAsGraph(filename); } else { if ( SgProject::get_verbose() >= 1 ) printf ("Skip the output of the DOT graph from the SgFile IR node (SgProject will be traversed) \n"); } } // cout << "done." << endl; break; } // DQ (7/23/2005): Implemented default case to avoid g++ warnings // about enum values not handled by this switch default: { // nothing to do here break; } } d.node = node; return d; }
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.
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); }