void visitorTraversal::analyzePath(vector<VertexID>& pth) { std::vector<VertexID> pathR = pth; std::vector<SgGraphNode*> path; for (unsigned int j = 0; j < pathR.size(); j++) { SgGraphNode* R = (*orig)[pathR[j]].sg; path.push_back(R); } for (unsigned int k = 0; k < path.size(); k++) { if (isSgFunctionRefExp(path[k]->get_SgNode())) { SgFunctionRefExp* sfrd = isSgFunctionRefExp(path[k]->get_SgNode()); SgFunctionDeclaration* fd = sfrd->getAssociatedFunctionDeclaration(); fd = isSgFunctionDeclaration(fd->get_definingDeclaration()); assert(fd!=NULL); SgFunctionDefinition* fdd = fd->get_definition(); SgName sname = fdd->get_mangled_name(); string sn = sname.getString(); if (find(defstr.begin(), defstr.end(), sn) == defstr.end()) { defstr.push_back(sn); defs.push_back(fdd); std::cout << "found new sn: " << sn << std::endl; } else { std::cout << "found old sn: " << sn << std::endl; } } } #pragma omp atomic paths++; }
/////////////////////////////////////////////////////////////////////////////////// The CompassAnalyses::NoExitInMpiCode::Traversal::visit(SgNode* node) /// function implements a simple AST traversal seeking out SgFunctionRefExp /// nodes for function reference expressions corresponding to MPI Init and /// Finalize and calls to exit() nested in those blocks; these are reported /// as checker violations. /// /// \param node is a SgNode* //////////////////////////////////////////////////////////////////////////////// void CompassAnalyses::NoExitInMpiCode::Traversal::visit(SgNode* node) { static bool usedMPI = false; SgFunctionRefExp *sgfrexp = isSgFunctionRefExp(node); if( sgfrexp != NULL ) { std::string sgfrexpName = sgfrexp->get_symbol()->get_name().getString(); if( sgfrexpName == "MPI_Init" ) { usedMPI = true; } //if( sgfrexpNam == "MPI_Init" ) if( sgfrexpName == "MPI_Finalize" ) { usedMPI = false; } //if( sgfrexpName == "MPI_Finalize" ) //#ASR:07/07/10 //fixed object creation of CheckerOutput for Cxx standard if( usedMPI == true && sgfrexpName == "exit" ) { output->addOutput( new CompassAnalyses::NoExitInMpiCode::CheckerOutput( node ) ); //output->addOutput( new CompassAnalyses::NoExitInMpiCode::CheckerOutput::CheckerOutput( node ) ); } //if( usedMPI == true && sgfrexpName == "exit" ) } //if( sgfrexp != NULL ) return; } //visit(SgNode *node)
void CompassAnalyses::NoVariadicFunctions::Traversal:: visit(SgNode* node) { switch( node->variantT() ) { case V_SgFunctionRefExp: { SgFunctionRefExp *fref = isSgFunctionRefExp(node); ROSE_ASSERT(fref != NULL); SgFunctionDeclaration *fdecl = fref->get_symbol()->get_declaration(); this->functionDeclarationHandler( fdecl, fref ); } break; //case V_SgFunctionRefExp case V_SgMemberFunctionRefExp: { SgMemberFunctionRefExp *fref = isSgMemberFunctionRefExp(node); ROSE_ASSERT(fref != NULL); SgFunctionDeclaration *fdecl = fref->get_symbol()->get_declaration(); this->functionDeclarationHandler( fdecl, fref ); } break; //case V_SgMemberFunctionRefExp default: break; } //switch( node->variantT() ) return; } //End of the visit function.
void CompassAnalyses::StringTokenToIntegerConverter::Traversal:: visit(SgNode* node) { // Implement your traversal here. if(isSgFunctionCallExp(node)) { SgFunctionCallExp* callSite = isSgFunctionCallExp(node); if(callSite->get_function() != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(callSite->get_function()); if(functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); std::string functionName = functionSymbol->get_name().getString(); if(functionName == "atoi" || functionName == "atol" || functionName == "atoll" || functionName == "sscanf" ) { output->addOutput(new CheckerOutput(node)); } } } } } //End of the visit function.
void specificationTraversal::visit(SgNode* n) { if (isSgFunctionCallExp(n) != NULL) { SgFunctionCallExp* funcCallExp = isSgFunctionCallExp(n); SgFunctionRefExp* funcRefExp = isSgFunctionRefExp(funcCallExp->get_function()); string functionName = funcRefExp->get_symbol()->get_declaration()->get_name().getString(); #if DEBUG cout << " Found Function Name: " << functionName << endl; #endif LayoutOptions::LayoutType type = LayoutOptions::getLayoutType(functionName); switch (type) { case LayoutOptions::InterleaveAcrossArrays: handleInterLeaveAcrossArrays(funcCallExp); break; case LayoutOptions::UnknownTransformation: break; default: cout << " Unknown layout type option. " << endl; ROSE_ABORT(); } } }
// Note: this now (11/7/2008) considers pointer derefs and array derefs safe, // which doesn't preserve invalid memory access behavior bool isSimpleInitializer(SgExpression* e) { if (isSgVarRefExp(e)) return true; if (isSgValueExp(e)) return true; if (isSgUnaryOp(e) && isSimpleInitializer(isSgUnaryOp(e)->get_operand())) { return isSgBitComplementOp(e) || isSgMinusOp(e) || isSgNotOp(e) || isSgUnaryAddOp(e) || isSgCastExp(e) || isSgPointerDerefExp(e); } if (isSgBinaryOp(e) && isSimpleInitializer(isSgBinaryOp(e)->get_lhs_operand()) && isSimpleInitializer(isSgBinaryOp(e)->get_rhs_operand())) { return isSgAddOp(e) || isSgAndOp(e) || isSgBitAndOp(e) || isSgBitOrOp(e) || isSgBitXorOp(e) || isSgCommaOpExp(e) || isSgDivideOp(e) || isSgEqualityOp(e) || isSgGreaterOrEqualOp(e) || isSgGreaterThanOp(e) || isSgLessOrEqualOp(e) || isSgLessThanOp(e) || isSgLshiftOp(e) || isSgModOp(e) || isSgMultiplyOp(e) || isSgNotEqualOp(e) || isSgOrOp(e) || isSgRshiftOp(e) || isSgSubtractOp(e) || isSgPntrArrRefExp(e); } if (isSgConditionalExp(e)) { SgConditionalExp* c = isSgConditionalExp(e); return isSimpleInitializer(c->get_conditional_exp()) && isSimpleInitializer(c->get_true_exp()) && isSimpleInitializer(c->get_false_exp()); } if (isSgFunctionCallExp(e)) { SgFunctionRefExp* fr = isSgFunctionRefExp(isSgFunctionCallExp(e)->get_function()); if (!fr) return false; SgFunctionDeclaration* decl = fr->get_symbol()->get_declaration(); if (safe_functions.find(decl) == safe_functions.end()) { return false; } const SgExpressionPtrList& args = isSgFunctionCallExp(e)->get_args()->get_expressions(); for (size_t i = 0; i < args.size(); ++i) { if (!isSimpleInitializer(args[i])) return false; } return true; } return false; }
void CompassAnalyses::PreferFseekToRewind::Traversal:: visit(SgNode* node) { // Implement your traversal here. if(isSgFunctionCallExp(node)) { SgFunctionCallExp* callSite = isSgFunctionCallExp(node); if(callSite->get_function() != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(callSite->get_function()); if(functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); std::string functionName = functionSymbol->get_name().getString(); if(functionName == "rewind") { output->addOutput(new CheckerOutput(node)); } } } } } //End of the visit function.
static void run(Compass::Parameters parameters, Compass::OutputObject* output) { // We only care about source code in the user's space, not, // for example, Boost or system files. string target_directory = parameters["general::target_directory"].front(); CompassAnalyses::NoRand::source_directory.assign(target_directory); // Use the pre-built ROSE AST SgProject* sageProject = Compass::projectPrerequisite.getProject(); SgNode* root_node = (SgNode*) sageProject; // perform AST matching AstMatching matcher; MatchResult matches = matcher.performMatching("$r=SgFunctionRefExp", root_node); BOOST_FOREACH(SingleMatchVarBindings match, matches) { SgFunctionRefExp *function = (SgFunctionRefExp *)match["$r"]; std::string fncName = function->get_symbol()->get_name().getString(); if( fncName.find( "rand", 0, 4) != std::string::npos) { output->addOutput( new CompassAnalyses::NoRand::CheckerOutput(function)); } }
static bool ContainsNonSimpleCall(SgStatement *stmt) { static std::set< std::string > segDB ; bool containsUnknownCall = false ; if (segDB.empty()) { char funcName[128] ; FILE *fp ; if ((fp = fopen("SegDB.txt", "r")) != NULL) { while(fgets(funcName, 128, fp)) { funcName[strlen(funcName)-1] = 0 ; segDB.insert(funcName) ; } fclose(fp) ; } else { printf("File SEGDB.txt is absent. Sequential segment results degraded.\n") ; segDB.insert("_____") ; } } /* check to see if this statement contains any function calls */ Rose_STL_Container<SgNode*> calls = NodeQuery::querySubTree(stmt, V_SgFunctionCallExp) ; for (Rose_STL_Container<SgNode*>::iterator c_itr = calls.begin(); c_itr != calls.end(); ++c_itr) { SgFunctionCallExp *stmt = isSgFunctionCallExp(*c_itr) ; ROSE_ASSERT(stmt); SgFunctionRefExp *func = isSgFunctionRefExp(stmt->get_function()) ; if (func != NULL) { SgFunctionSymbol *funcName = func->get_symbol() ; if (segDB.find(funcName->get_name().getString()) == segDB.end()) { containsUnknownCall = true ; break ; } } else { /* Since I can't handle this case, assume the worst -- for now */ containsUnknownCall = true ; break ; } } return containsUnknownCall ; }
SgFunctionCallExp* fooCallCreate() { SgFunctionSymbol* funcSymb = new SgFunctionSymbol(fooDecl); SgFunctionRefExp* funcRefExp = new SgFunctionRefExp(SgDefaultFile, funcSymb); funcSymb->set_parent(funcRefExp); SgExprListExp* args = new SgExprListExp(SgDefaultFile); SgFunctionCallExp* funcCall = new SgFunctionCallExp(SgDefaultFile, funcRefExp, args); funcRefExp->set_parent(funcCall); args->set_parent(funcCall); return funcCall; }
int main( int argc, char * argv[] ) { // Build the AST used by ROSE SgProject* project = frontend(argc,argv); ROSE_ASSERT(project != NULL); // Build a list of functions within the AST Rose_STL_Container<SgNode*> functionCallList = NodeQuery::querySubTree (project,V_SgFunctionCallExp); int functionCounter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionCallList.begin(); i != functionCallList.end(); i++) { SgExpression* functionExpression = isSgFunctionCallExp(*i)->get_function(); ROSE_ASSERT(functionExpression != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression); SgFunctionSymbol* functionSymbol = NULL; if (functionRefExp != NULL) { // Case of non-member function functionSymbol = functionRefExp->get_symbol(); } else { // Case of member function (hidden in rhs of binary dot operator expression) SgDotExp* dotExp = isSgDotExp(functionExpression); ROSE_ASSERT(dotExp != NULL); functionExpression = dotExp->get_rhs_operand(); SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression); ROSE_ASSERT(memberFunctionRefExp != NULL); functionSymbol = memberFunctionRefExp->get_symbol(); } ROSE_ASSERT(functionSymbol != NULL); SgFunctionDeclaration* functionDeclaration = functionSymbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); // Output mapping of function calls to function declarations printf ("Location of function call #%d at line %d resolved by overloaded function declared at line %d \n", functionCounter++, isSgFunctionCallExp(*i)->get_file_info()->get_line(), functionDeclaration->get_file_info()->get_line()); } return 0; }
/* * Replace the op_par_loop with respective kernel function */ void OPSource::fixParLoops(SgNode *n) { SgName kernel_name; SgFunctionCallExp *fn = isSgFunctionCallExp(n); if(fn != NULL) { string fn_name = fn->getAssociatedFunctionDeclaration()->get_name().getString(); if(fn_name.compare("op_par_loop_2")==0 || fn_name.compare("op_par_loop_3")==0 || fn_name.compare("op_par_loop_4")==0 || fn_name.compare("op_par_loop_5")==0 || fn_name.compare("op_par_loop_6")==0 || fn_name.compare("op_par_loop_7")==0 || fn_name.compare("op_par_loop_8")==0 || fn_name.compare("op_par_loop_9")==0) { SgExprListExp* exprList = fn->get_args(); SgExpressionPtrList &exprs = exprList->get_expressions(); SgFunctionRefExp* varExp = isSgFunctionRefExp(exprs[0]); if(varExp != NULL) { kernel_name = varExp->get_symbol()->get_name(); } exprs.erase(exprs.begin()); SgExpressionPtrList::iterator it = exprs.begin() + op_par_loop_args::num_params - 1; for(; it != exprs.end(); it += op_argument::num_params) { *it = buildCastExp( *it, buildPointerType(SgClassType::createType( buildStructDeclaration("op_dat<void>"))) ); } // Inject Name exprs.insert(exprs.begin(), buildStringVal(kernel_name)); // Fetch the declaration SgName name = SgName("op_par_loop_") + kernel_name; SgFunctionDeclaration *funcDecl = cudaFunctionDeclarations[kernel_name]; if(funcDecl) { SgFunctionRefExp* ref = isSgFunctionRefExp(fn->get_function()); SgFunctionSymbol *symbol = ref->get_symbol(); symbol->set_declaration(funcDecl); ref->set_symbol(symbol); fn->set_function(ref); } } } }
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 CompassAnalyses::NoRand::Traversal:: visit(SgNode* node) { const int STRING_LEN_RAND = 4; SgFunctionRefExp *sgFuncRef = isSgFunctionRefExp( node ); if( sgFuncRef != NULL ) { std::string fncName = sgFuncRef->get_symbol()->get_name().getString(); if( fncName.find( "rand", 0, STRING_LEN_RAND ) != std::string::npos ) { output->addOutput( new CheckerOutput( node ) ); } //if( fncName.find("vfork", 0, STRING_LEN_RAND) != std::string::npos ) } //if( sgFuncRef != NULL ) return; } //End of the visit function.
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; }
void mlmTransform::transformCallExp(SgCallExpression* callExp) { ROSE_ASSERT(callExp); SgFunctionRefExp* funcName = isSgFunctionRefExp(callExp->get_function()); if(!funcName) return; SgExprListExp* funcArgList = callExp->get_args(); SgExpressionPtrList argList = funcArgList->get_expressions(); SgScopeStatement* scope = getScope(callExp); //cout << funcName->get_symbol()->get_name() << endl; /** if it is malloc, search for the mlm attribute and append the memory level **/ if(strncmp("malloc",funcName->get_symbol()->get_name().str(),6) == 0) { if(argList.size() != 1) return; SgExprListExp* funcArgList = callExp->get_args(); // check if LHS of malloc has an attribute assigned SgNode* parentNode = callExp->get_parent(); // parent node can be a casting expression if(isSgCastExp(parentNode)) { parentNode = parentNode->get_parent(); } // the mlm attribute AstAttribute* attr = NULL; // So far we spot two candidates for parentNode that we need to transform if(isSgAssignOp(parentNode)) { SgAssignOp* assignOp = isSgAssignOp(parentNode); SgExpression* lhs = isSgExpression(assignOp->get_lhs_operand()); if(!isSgVarRefExp(lhs)) { //cout << "lhs:" << assignOp->get_lhs_operand()->class_name() << endl; // if pointer is packaged inside a struct, then we need to look down in lhs. if(isSgDotExp(lhs)) { lhs = isSgDotExp(lhs)->get_rhs_operand(); } } SgVarRefExp* lhsVarRef = isSgVarRefExp(lhs); ROSE_ASSERT(lhsVarRef); SgSymbol* symbol = lhsVarRef->get_symbol(); ROSE_ASSERT(symbol); //retrieve the attribute from symbol attr = symbol->getAttribute("mlmAttribute"); //cout << "LHS symbol name: " << symbol->get_name() << endl; } else if(isSgAssignInitializer(parentNode)) { SgInitializedName* initName = isSgInitializedName(parentNode->get_parent()); ROSE_ASSERT(initName); SgSymbol* symbol = initName->get_symbol_from_symbol_table(); if(!symbol) return; ROSE_ASSERT(symbol); //retrieve the attribute from symbol attr = symbol->getAttribute("mlmAttribute"); //cout << "Initialized symbol name: " << symbol->get_name() << endl; } else { // do nothing because no attribute assigned or we always set to default } // if there is a mlm attribute attached to the symbol, then create new malloc if(attr) { mlmAttribute* mlmAttr = dynamic_cast<mlmAttribute*> (attr); SgExprListExp* funcArgList = callExp->get_args(); funcArgList->append_expression(buildIntVal(mlmAttr->getMemType())); replaceExpression(callExp, buildFunctionCallExp("mlm_malloc",deepCopy(callExp->get_type()),deepCopy(funcArgList),getScope(callExp))); } } else if(strncmp("memcpy",funcName->get_symbol()->get_name().str(),6) == 0) { // cout << "replacing memcpy" << endl; if(argList.size() != 3) return; Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree(funcArgList, V_SgVarRefExp); SgVarRefExp* dst = isSgVarRefExp(varList[0]); SgVarRefExp* src = isSgVarRefExp(varList[1]); AstAttribute* attrDst = dst->get_symbol()->getAttribute("mlmAttribute"); AstAttribute* attrSrc = src->get_symbol()->getAttribute("mlmAttribute"); mlmAttribute* mlmAttrDst = dynamic_cast<mlmAttribute*>(attrDst); mlmAttribute* mlmAttrSrc = dynamic_cast<mlmAttribute*>(attrSrc); // if((mlmAttrDst && !mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() < mlmAttrDst->getMemType()))) // { // replaceExpression(callExp, buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),true); // DeletepragmasList2.push_back(callExp); // } // // else if((!mlmAttrDst && mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() > mlmAttrDst->getMemType()))) // 09/30/14 Following Simon's suggestion, we always insert wait for the mlm_memcpy // { string tagName = generateUniqueVariableName(scope,"copy_tag"); SgVariableDeclaration* newDecl = buildVariableDeclaration(tagName, buildOpaqueType("mlm_Tag",getGlobalScope(callExp)), buildAssignInitializer(buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope))); SgExprStatement* waitStmt = buildFunctionCallStmt("mlm_waitComplete", buildVoidType(), buildExprListExp(buildVarRefExp(tagName,scope)), scope); insertStatement(getEnclosingStatement(callExp),newDecl,true); insertStatement(getEnclosingStatement(callExp),waitStmt,true); removeStatement(getEnclosingStatement(callExp)); // } } else if(strncmp("free",funcName->get_symbol()->get_name().str(),4) == 0) { // cout << "replacing free" << endl; if(argList.size() != 1) return; SgExpression* varExp = isSgExpression(argList[0]); //cout << "exp:" << varExp->class_name() << endl; if(!isSgVarRefExp(varExp)) { if(isSgCastExp(varExp)) { varExp = isSgCastExp(varExp)->get_operand_i(); } // if pointer is packaged inside a struct, then we need to look down in lhs. if(isSgDotExp(varExp)) { varExp = isSgDotExp(varExp)->get_rhs_operand(); } } SgVarRefExp* varRef = isSgVarRefExp(varExp); ROSE_ASSERT(varRef); AstAttribute* attr = varRef->get_symbol()->getAttribute("mlmAttribute"); if(attr) { replaceExpression(callExp, buildFunctionCallExp("mlm_free",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),false); } } }
void ControlDependenceGraph::_buildInterprocedural() { // Go through the SGNODE dependence nodes and create the appropriate // call site nodes, entry nodes etc. SgFunctionDefinition *func = isSgFunctionDefinition(_head); ROSE_ASSERT(func != NULL); // First create the entry node for the procedure _interprocedural->procedureEntry.entry = new DependenceNode(DependenceNode::ENTRY, func->get_declaration()); DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry); // Link the entry node up with all the nodes in the CDG which do not have // predecessors for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++) { DependenceNode *node = dynamic_cast < DependenceNode * >(*i); if ((node->numPredecessors() == 0) && (node != entry)) { establishEdge(entry, node); } } // create a formal out return argument, control dependent on the entry // node string return_name = func->get_declaration()->get_name().str(); return_name = return_name + " return"; _interprocedural->procedureEntry.formal_return = new DependenceNode(DependenceNode::FORMALOUT, return_name); DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return); establishEdge(entry, formal_return); // for each of the arguments in the function parameter list, add a // formal-in and formal-out node SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList(); SgInitializedNamePtrList params = paramlist->get_args(); for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++) { SgInitializedName *name = *i; DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN, name->get_name().str()); DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT, name->get_name().str()); establishEdge(entry, createNode(formal_in)); establishEdge(entry, createNode(formal_out)); _interprocedural->procedureEntry.formal_in[name] = formal_in; _interprocedural->procedureEntry.formal_out[name] = formal_out; // To preserve the order of arguments, we insert them into arg_order _interprocedural->procedureEntry.arg_order.push_back(name); } // Now we go through each of the SgNodes in our CDG. If any of them // contain a function call, we want to build a call site node for them. map < SgNode *, DependenceNode * >::iterator sgnode_iterator; for (sgnode_iterator = _sgnode_map.begin(); sgnode_iterator != _sgnode_map.end(); sgnode_iterator++) { SgNode *currnode = sgnode_iterator->first; list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode); if (calls.empty()) continue; for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++) { SgFunctionCallExp *call = *i; // This needs to be replaced with some call graph analysis SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function()); ROSE_ASSERT(func != NULL); SgName func_name = func->get_symbol()->get_name(); InterproceduralInfo::CallSiteStructure callstructure; callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call); // the call site is control dependent on the statement (i.e. for // the call site to happen, the statement must be executed) DependenceNode *callsite = createNode(callstructure.callsite); // addLink(callsite, getNode(currnode)); establishEdge(getNode(currnode), callsite); // create an actual out node for the return value, control // dependent on callsite string return_name = func_name.str(); return_name = return_name + " return"; callstructure.actual_return = new DependenceNode(DependenceNode::ACTUALOUT, return_name); DependenceNode *actual_return = createNode(callstructure.actual_return); establishEdge(callsite, actual_return); // For each argument in the function call, build an actual_in and // actual_out, control dependent on callsite SgExpressionPtrList args = call->get_args()->get_expressions(); for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++) { SgExpression *arg = *j; DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg); DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg); establishEdge(callsite, createNode(actual_in)); establishEdge(callsite, createNode(actual_out)); callstructure.actual_in[arg] = actual_in; callstructure.actual_out[arg] = actual_out; // To preserve the order of expressions in the parameter list, // // we insert them into expr_order callstructure.expr_order.push_back(arg); } // add the callstructure to interprocedural info _interprocedural->callsite_map[call] = callstructure; } } }
SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCall) { SgFunctionDeclaration *funcDec = NULL; SgExpression *expression = functionCall->get_function(); ROSE_ASSERT(expression != NULL); switch(expression->variantT()) { case V_SgMemberFunctionRefExp: { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(expression); ROSE_ASSERT(memberFunctionRefExp != NULL); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgDotExp: { SgDotExp *dotExp = isSgDotExp(expression); ROSE_ASSERT(dotExp != NULL); if(dotExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(dotExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgArrowExp: { SgArrowExp *arrowExp = isSgArrowExp(expression); ROSE_ASSERT(arrowExp != NULL); if(arrowExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(arrowExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(expression); ROSE_ASSERT(functionRefExp != NULL); // found a standard function reference funcDec = functionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgPointerDerefExp: { ROSE_ABORT(); break; } default: { ROSE_ABORT(); } } return funcDec; }
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; }
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); }
void FortranProgramDeclarationsAndDefinitions::visit (SgNode * node) { using boost::filesystem::path; using boost::filesystem::system_complete; using boost::iequals; using boost::starts_with; using boost::lexical_cast; using std::string; if (isSgSourceFile (node)) { path p = system_complete (path (isSgSourceFile (node)->getFileName ())); currentSourceFile = p.filename (); Debug::getInstance ()->debugMessage ("Source file '" + currentSourceFile + "' detected", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__ ); } else if (Globals::getInstance ()->isInputFile (currentSourceFile)) { /* * ====================================================== * Only process this portion of the AST if we recognise * this source file as one passed on the command line. In * Fortran, .rmod files are sometimes generated whose * traversal should be avoided * ====================================================== */ switch (node->variantT ()) { case V_SgModuleStatement: { SgModuleStatement * moduleStatement = isSgModuleStatement (node); currentModuleName = moduleStatement->get_name ().getString (); fileNameToModuleNames[currentSourceFile].push_back (currentModuleName); moduleNameToFileName[currentModuleName] = currentSourceFile; Debug::getInstance ()->debugMessage ("Module '" + currentModuleName + "' in file '" + currentSourceFile + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__ ); break; } case V_SgProcedureHeaderStatement: { /* * ====================================================== * We need to store all subroutine definitions since we * later have to copy and modify the user kernel subroutine * ====================================================== */ SgProcedureHeaderStatement * procedureHeaderStatement = isSgProcedureHeaderStatement (node); string const subroutineName = procedureHeaderStatement->get_name ().getString (); subroutinesInSourceCode[subroutineName] = procedureHeaderStatement; ROSE_ASSERT (currentModuleName.size() > 0); moduleNameToSubroutines[currentModuleName].push_back (subroutineName); subroutineToFileName[subroutineName] = currentSourceFile; Debug::getInstance ()->debugMessage ( "Found procedure header statement '" + procedureHeaderStatement->get_name ().getString () + "' in file '" + currentSourceFile + "', and module '" + currentModuleName + "'", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); break; } case V_SgFunctionCallExp: { /* * ====================================================== * Function call found in the AST. Get its actual arguments * and the callee name * ====================================================== */ SgFunctionCallExp * functionCallExp = isSgFunctionCallExp (node); SgExprListExp * actualArguments = functionCallExp->get_args (); string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call '" + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); if ( iequals (calleeName, OP2::OP_DECL_SET) || iequals (calleeName, OP2::OP_DECL_SET_HDF5) ) { /* * ====================================================== * An OP_SET variable declared through an OP_DECL_SET call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_SET_HDF5) ) isHDF5Format = true; FortranOpSetDefinition * opSetDeclaration = new FortranOpSetDefinition (actualArguments, isHDF5Format); OpSetDefinitions[opSetDeclaration->getVariableName ()] = opSetDeclaration; } else if ( iequals (calleeName, OP2::OP_DECL_MAP) || iequals (calleeName, OP2::OP_DECL_MAP_HDF5) ) { /* * ====================================================== * An OP_MAP variable declared through an OP_DECL_MAP call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_MAP_HDF5) ) { isHDF5Format = true; Debug::getInstance ()->debugMessage ("This is the HDF5 version: '" + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } FortranOpMapDefinition * opMapDeclaration = new FortranOpMapDefinition (actualArguments, isHDF5Format); OpMapDefinitions[opMapDeclaration->getVariableName ()] = opMapDeclaration; } else if ( iequals (calleeName, OP2::OP_DECL_DAT) || iequals (calleeName, OP2::OP_DECL_DAT_HDF5) ) { /* * ====================================================== * An OP_DAT variable declared through an OP_DECL_DAT call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_DAT_HDF5) ) isHDF5Format = true; FortranOpDatDefinition * opDatDeclaration = new FortranOpDatDefinition (actualArguments, isHDF5Format); OpDatDefinitions[opDatDeclaration->getVariableName ()] = opDatDeclaration; } else if (iequals (calleeName, OP2::OP_DECL_CONST)) { /* * ====================================================== * A constant declared through an OP_DECL_CONST call * ====================================================== */ FortranOpConstDefinition * opConstDeclaration = new FortranOpConstDefinition (actualArguments, functionCallExp); OpConstDefinitions[opConstDeclaration->getVariableName ()] = opConstDeclaration; } else if (starts_with (calleeName, OP2::OP_PAR_LOOP)) { /* * ====================================================== * The first argument to an 'OP_PAR_LOOP' call should be * a reference to the kernel function. Cast it and proceed, * otherwise throw an exception * ====================================================== */ SgExprListExp * actualArguments = functionCallExp->get_args (); SgFunctionRefExp * functionRefExpression = isSgFunctionRefExp ( actualArguments->get_expressions ().front ()); ROSE_ASSERT (functionRefExpression != NULL); string const userSubroutineName = functionRefExpression->getAssociatedFunctionDeclaration ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found '" + calleeName + "' with (host) user subroutine '" + userSubroutineName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); if (parallelLoops.find (userSubroutineName) == parallelLoops.end ()) { int numberOfOpArgs = getLoopSuffixNumber ( calleeName ); /* * ====================================================== * If this kernel has not been previously encountered then * build a new parallel loop representation * ====================================================== */ FortranParallelLoop * parallelLoop = new FortranParallelLoop ( functionCallExp); parallelLoop->addFileName (currentSourceFile); parallelLoops[userSubroutineName] = parallelLoop; Debug::getInstance ()->debugMessage ("Parallel loop with '" + lexical_cast <string> (numberOfOpArgs) + "' arguments", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); analyseParallelLoopArguments (parallelLoop, actualArguments, numberOfOpArgs); parallelLoop->checkArguments (); parallelLoop->setIncrementalID (IDCounter); IDCounter++; } else { Debug::getInstance ()->debugMessage ("Parallel loop for '" + userSubroutineName + "' already created", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); ParallelLoop * parallelLoop = parallelLoops[userSubroutineName]; parallelLoop->addFunctionCallExpression (functionCallExp); parallelLoop->addFileName (currentSourceFile); } } break; } default: { break; } } } }
set<SgInitializedName*> computeLiveVars(SgStatement* stmt, const X86CTranslationPolicy& conv, map<SgLabelStatement*, set<SgInitializedName*> >& liveVarsForLabels, set<SgInitializedName*> currentLiveVars, bool actuallyRemove) { switch (stmt->variantT()) { case V_SgBasicBlock: { const SgStatementPtrList& stmts = isSgBasicBlock(stmt)->get_statements(); for (size_t i = stmts.size(); i > 0; --i) { currentLiveVars = computeLiveVars(stmts[i - 1], conv, liveVarsForLabels, currentLiveVars, actuallyRemove); } return currentLiveVars; } case V_SgPragmaDeclaration: return currentLiveVars; case V_SgDefaultOptionStmt: return currentLiveVars; case V_SgCaseOptionStmt: { return computeLiveVars(isSgCaseOptionStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove); } case V_SgLabelStatement: { liveVarsForLabels[isSgLabelStatement(stmt)] = currentLiveVars; return currentLiveVars; } case V_SgGotoStatement: { return liveVarsForLabels[isSgGotoStatement(stmt)->get_label()]; } case V_SgSwitchStatement: { SgSwitchStatement* s = isSgSwitchStatement(stmt); SgBasicBlock* swBody = isSgBasicBlock(s->get_body()); ROSE_ASSERT (swBody); const SgStatementPtrList& bodyStmts = swBody->get_statements(); set<SgInitializedName*> liveForBody; // Assumes any statement in the body is possible for (size_t i = 0; i < bodyStmts.size(); ++i) { setUnionInplace(liveForBody, computeLiveVars(bodyStmts[i], conv, liveVarsForLabels, currentLiveVars, actuallyRemove)); } return computeLiveVars(s->get_item_selector(), conv, liveVarsForLabels, liveForBody, actuallyRemove); } case V_SgContinueStmt: { return makeAllPossibleVars(conv); } case V_SgIfStmt: { set<SgInitializedName*> liveForBranches = computeLiveVars(isSgIfStmt(stmt)->get_true_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove); setUnionInplace(liveForBranches, (isSgIfStmt(stmt)->get_false_body() != NULL ? computeLiveVars(isSgIfStmt(stmt)->get_false_body(), conv, liveVarsForLabels, currentLiveVars, actuallyRemove) : set<SgInitializedName*>())); return computeLiveVars(isSgIfStmt(stmt)->get_conditional(), conv, liveVarsForLabels, liveForBranches, actuallyRemove); } case V_SgWhileStmt: { while (true) { set<SgInitializedName*> liveVarsSave = currentLiveVars; currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, false); currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_condition(), conv, liveVarsForLabels, currentLiveVars, false); setUnionInplace(currentLiveVars, liveVarsSave); if (liveVarsSave == currentLiveVars) break; } if (actuallyRemove) { set<SgInitializedName*> liveVarsSave = currentLiveVars; currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_body(), conv, liveVarsForLabels, currentLiveVars, true); currentLiveVars = computeLiveVars(isSgWhileStmt(stmt)->get_condition(), conv, liveVarsForLabels, currentLiveVars, true); setUnionInplace(currentLiveVars, liveVarsSave); } return currentLiveVars; } case V_SgBreakStmt: return set<SgInitializedName*>(); case V_SgExprStatement: { SgExpression* e = isSgExprStatement(stmt)->get_expression(); switch (e->variantT()) { case V_SgAssignOp: { SgVarRefExp* lhs = isSgVarRefExp(isSgAssignOp(e)->get_lhs_operand()); ROSE_ASSERT (lhs); SgInitializedName* in = lhs->get_symbol()->get_declaration(); if (currentLiveVars.find(in) == currentLiveVars.end()) { if (actuallyRemove) { // cerr << "Removing assignment " << e->unparseToString() << endl; isSgStatement(stmt->get_parent())->remove_statement(stmt); } return currentLiveVars; } else { currentLiveVars.erase(in); getUsedVariables(isSgAssignOp(e)->get_rhs_operand(), currentLiveVars); return currentLiveVars; } } case V_SgFunctionCallExp: { getUsedVariables(e, currentLiveVars); SgFunctionRefExp* fr = isSgFunctionRefExp(isSgFunctionCallExp(e)->get_function()); ROSE_ASSERT (fr); if (fr->get_symbol()->get_declaration() == conv.interruptSym->get_declaration()) { setUnionInplace(currentLiveVars, makeAllPossibleVars(conv)); return currentLiveVars; } else { return currentLiveVars; } } default: { getUsedVariables(e, currentLiveVars); return currentLiveVars; } } } case V_SgVariableDeclaration: { ROSE_ASSERT (isSgVariableDeclaration(stmt)->get_variables().size() == 1); SgInitializedName* in = isSgVariableDeclaration(stmt)->get_variables()[0]; bool isConst = isConstType(in->get_type()); if (currentLiveVars.find(in) == currentLiveVars.end() && isConst) { if (actuallyRemove) { // cerr << "Removing decl " << stmt->unparseToString() << endl; isSgStatement(stmt->get_parent())->remove_statement(stmt); } return currentLiveVars; } else { currentLiveVars.erase(in); if (in->get_initializer()) { getUsedVariables(in->get_initializer(), currentLiveVars); } return currentLiveVars; } } default: cerr << "computeLiveVars: " << stmt->class_name() << endl; abort(); } }
int main( int argc, char* argv[] ) { // Initialize and check compatibility. See rose::initialize ROSE_INITIALIZE; SgProject* project = frontend(argc,argv); AstTests::runAllTests(project); #if 0 // Output the graph so that we can see the whole AST graph, for debugging. generateAstGraph(project, 4000); #endif #if 1 printf ("Generate the dot output of the SAGE III AST \n"); generateDOT ( *project ); printf ("DONE: Generate the dot output of the SAGE III AST \n"); #endif // There are lots of way to write this, this is one simple approach; get all the function calls. std::vector<SgNode*> functionCalls = NodeQuery::querySubTree (project,V_SgFunctionCallExp); // Find the SgFunctionSymbol for snprintf so that we can reset references to "sprintf" to "snprintf" instead. // SgGlobal* globalScope = (*project)[0]->get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(project->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal* globalScope = sourceFile->get_globalScope(); SgFunctionSymbol* snprintf_functionSymbol = globalScope->lookup_function_symbol("snprintf"); ROSE_ASSERT(snprintf_functionSymbol != NULL); // Iterate over the function calls to find the calls to "sprintf" for (unsigned long i = 0; i < functionCalls.size(); i++) { SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(functionCalls[i]); ROSE_ASSERT(functionCallExp != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); if (functionSymbol != NULL) { SgName functionName = functionSymbol->get_name(); // printf ("Function being called: %s \n",functionName.str()); if (functionName == "sprintf") { // Now we have something to do! functionRefExp->set_symbol(snprintf_functionSymbol); // Now add the "n" argument SgExprListExp* functionArguments = functionCallExp->get_args(); SgExpressionPtrList & functionArgumentList = functionArguments->get_expressions(); // "sprintf" shuld have exactly 2 arguments (I guess the "..." don't count) printf ("functionArgumentList.size() = %zu \n",functionArgumentList.size()); // ROSE_ASSERT(functionArgumentList.size() == 2); SgExpressionPtrList::iterator i = functionArgumentList.begin(); // printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str()); SgVarRefExp* variableRefExp = isSgVarRefExp(*i); ROSE_ASSERT(variableRefExp != NULL); // printf ("variableRefExp->get_type() = %p = %s = %s \n",variableRefExp->get_type(),variableRefExp->get_type()->class_name().c_str(),SageInterface::get_name(variableRefExp->get_type()).c_str()); SgType* bufferType = variableRefExp->get_type(); SgExpression* bufferLengthExpression = NULL; switch(bufferType->variantT()) { case V_SgArrayType: { SgArrayType* arrayType = isSgArrayType(bufferType); bufferLengthExpression = arrayType->get_index(); break; } case V_SgPointerType: { // SgPointerType* pointerType = isSgPointerType(bufferType); SgInitializedName* variableDeclaration = variableRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(variableDeclaration != NULL); SgExpression* initializer = variableDeclaration->get_initializer(); if (initializer != NULL) { SgAssignInitializer* assignmentInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignmentInitializer != NULL); // This is the rhs of the initialization of the pointer (likely a malloc through a cast). // This assumes: buffer = (char*) malloc(bufferLengthExpression); SgExpression* initializationExpression = assignmentInitializer->get_operand(); ROSE_ASSERT(initializationExpression != NULL); SgCastExp* castExp = isSgCastExp(initializationExpression); ROSE_ASSERT(castExp != NULL); SgFunctionCallExp* functionCall = isSgFunctionCallExp(castExp->get_operand()); ROSE_ASSERT(functionCall != NULL); SgExprListExp* functionArguments = isSgExprListExp(functionCall->get_args()); bufferLengthExpression = functionArguments->get_expressions()[0]; ROSE_ASSERT(bufferLengthExpression != NULL); } else { printf ("Initializer not found, so no value for n in snprintf can be computed currently \n"); } break; } default: { printf ("Error: default reached in evaluation of buffer type = %p = %s \n",bufferType,bufferType->class_name().c_str()); ROSE_ASSERT(false); } } ROSE_ASSERT(bufferLengthExpression != NULL); // printf ("bufferLengthExpression = %p = %s = %s \n",bufferLengthExpression,bufferLengthExpression->class_name().c_str(),SageInterface::get_name(bufferLengthExpression).c_str()); // Jump over the first argument, the "n" is defined to be the 2nd argument (the rest are shifted one position). i++; // Build a deep copy of the expression used to define the static buffer (could be any complex expression). SgTreeCopy copy_help; SgExpression* bufferLengthExpression_copy = isSgExpression(bufferLengthExpression->copy(copy_help)); // Insert the "n" for the parameter list to work with "snprintf" instead of "sprintf" functionArgumentList.insert(i,bufferLengthExpression_copy); } } } } return backend(project); }
void SimpleInstrumentation::visit ( SgNode* astNode ) { switch(astNode->variantT()) { case V_SgFunctionCallExp: { SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(astNode); SgExpression *function = functionCallExp->get_function(); ROSE_ASSERT(function); switch (function->variantT()) { case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(function); SgFunctionSymbol *symbol = functionRefExp->get_symbol(); ROSE_ASSERT(symbol != NULL); SgFunctionDeclaration *functionDeclaration = symbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); if (symbol == functionSymbol) { // Now we know that we have found the correct function call // (even in the presence of overloading or other forms of hidding) // Now fixup the symbol and type of the SgFunctionRefExp object to // reflect the new function to be called (after this we still have to // fixup the argument list in the SgFunctionCallExp. // We only want to build the decalration once (and insert it into the global scope) // after that we save the symbol and reuse it. if (newFunctionSymbol == NULL) { SgFunctionType* originalFunctionType = isSgFunctionType(functionSymbol->get_type()); ROSE_ASSERT(originalFunctionType != NULL); newFunctionSymbol = buildNewFunctionDeclaration (TransformationSupport::getStatement(astNode),originalFunctionType); } ROSE_ASSERT(newFunctionSymbol != NULL); ROSE_ASSERT(newFunctionSymbol->get_type() != NULL); functionRefExp->set_symbol(newFunctionSymbol); } break; } default: cerr<<"warning: unrecognized variant: "<<function->class_name(); } break; } case V_SgFunctionDeclaration: { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); string functionName = functionDeclaration->get_name().str(); if (functionName == "send") { SgFunctionType *functionType = functionDeclaration->get_type(); ROSE_ASSERT(functionType != NULL); bool foundFunction = false; if (functionType->get_return_type()->unparseToString() == "ssize_t") { SgTypePtrList & argumentList = functionType->get_arguments(); SgTypePtrList::iterator i = argumentList.begin(); if ( (*i++)->unparseToString() == "int" ) if ( (*i++)->unparseToString() == "const void *" ) if ( (*i++)->unparseToString() == "size_t" ) if ( (*i++)->unparseToString() == "int" ) foundFunction = true; } if (foundFunction == true) { // Now get the sysmbol using functionType SgScopeStatement *scope = functionDeclaration->get_scope(); ROSE_ASSERT(scope != NULL); functionSymbol = scope->lookup_function_symbol (functionName,functionType); } } break; } default: { // No other special cases } } }