int main(int argc, char** argv) { SgProject* project = frontend(argc, argv); AstTests::runAllTests(project); // Copy a defining function declaration SgFunctionDeclaration* func= findDeclarationStatement<SgFunctionDeclaration> (project, "bar", NULL, true); ROSE_ASSERT (func != NULL); SgFunctionDeclaration* func_copy = isSgFunctionDeclaration(copyStatement (func)); func_copy->set_name("bar_copy"); SgGlobal * glb = getFirstGlobalScope(project); appendStatement (func_copy,glb); #if 0 // this has been merged into fixStatement() called by appendStatement() SgFunctionSymbol *func_symbol = glb->lookup_function_symbol ("bar_copy", func_copy->get_type()); if (func_symbol == NULL); { func_symbol = new SgFunctionSymbol (func_copy); glb ->insert_symbol("bar_copy", func_symbol); } #endif //copy a non-defining function declaration SgFunctionDeclaration* nfunc= findDeclarationStatement<SgFunctionDeclaration> (project, "foo", NULL, false); ROSE_ASSERT (nfunc != NULL); func_copy = isSgFunctionDeclaration(copyStatement (nfunc)); glb = getFirstGlobalScope(project); appendStatement (func_copy,glb); //copy another non-defining function declaration nfunc= findDeclarationStatement<SgFunctionDeclaration> (project, "bar", NULL, false); ROSE_ASSERT (nfunc != NULL); func_copy = isSgFunctionDeclaration(copyStatement (nfunc)); glb = getFirstGlobalScope(project); appendStatement (func_copy,glb); AstTests::runAllTests(project); backend(project); return 0; }
static void set_rtedfunc(SgGlobal& n, const std::string& name, SgFunctionSymbol*& res) { res = n.lookup_function_symbol(rtedIdentifier(name)); presence_test(name, res); }
//! Return an expression like 8*sizeof(int)+ 3*sizeof(float) + 5*sizeof(double) for a list of variables accessed (either read or write) // For array variable, we should only count a single element access, not the entire array size // Algorithm: // Iterate on each variable in the set // group them into buckets based on types, using a map<SgType*, int> to store this // Iterate the list of buckets to generate count*sizeof(type) + .. expression SgExpression* calculateBytes (std::set<SgInitializedName*>& name_set, SgScopeStatement* scope, bool isRead) { SgExpression* result = NULL; if (name_set.size()==0) return result; // the input is essentially the loop body, a scope statement ROSE_ASSERT (scope != NULL); // We need to record the associated loop info. SgStatement* loop= NULL; SgForStatement* forloop = isSgForStatement(scope->get_scope()); SgFortranDo* doloop = isSgFortranDo(scope->get_scope()); if (forloop) loop = forloop; else if (doloop) loop = doloop; else { cerr<<"Error in CountLoadStoreBytes (): input is not loop body type:"<< scope->class_name()<<endl; assert(false); } std::map<SgType* , int> type_based_counters; // get all processed variables by inner loops std::set<SgInitializedName*> processed_var_set; getVariablesProcessedByInnerLoops (scope, isRead, processed_var_set); // fill in the type-based counters std::set<SgInitializedName*>::iterator set_iter; for (set_iter = name_set.begin(); set_iter != name_set.end(); set_iter++) { SgInitializedName* init_name = *set_iter; // skip visited variable when processing inner loops // some global variables may be visited by another function // But we should count it when processing the current function! // // We group all references to a same variable into one reference for now // if a variable is considered when processing inner loops, the variable // will be skipped when processing outer loops. if (isRead) { // if inner loops already processed it, skip it if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopLoadVariables[loop].insert(init_name); } else { if (processed_var_set.find(init_name) != processed_var_set.end()) continue; else LoopStoreVariables[loop].insert(init_name); } // It is tricky here, TODO consider pointer, typedefs, reference, modifier types SgType* stripped_type = (*set_iter)->get_type()->stripTypedefsAndModifiers(); SgType* base_type = NULL; if (isScalarType(stripped_type)) base_type = stripped_type; else if (isSgArrayType(stripped_type)) { // we may have multi-dimensional arrays like int a[][][]; base_type = stripped_type; do { base_type = isSgArrayType(base_type)->get_base_type(); } while (isSgArrayType (base_type)); } else { cerr<<"Error in calculateBytes(). Unhandled stripped type:"<<stripped_type->class_name()<<endl; assert (false); } type_based_counters[base_type] ++; } // end for // use the type-based counters for byte calculation std::map<SgType* , int>::iterator citer; //It is possible now to have zero after filtering out redundant variables //assert (type_based_counters.size()>0); for (citer = type_based_counters.begin(); citer !=type_based_counters.end(); citer ++) { SgType* t = (*citer).first; // at this point, we should not have array types any more ROSE_ASSERT (isSgArrayType (t) == false); int count = (*citer).second; assert (t != NULL); assert (count>0); SgExpression* sizeof_exp = NULL; if (is_Fortran_language()) { #if 0 // this does not work. cannot find func symbol for sizeof() // In Fortran sizeof() is a function call, not SgSizeOfOp. // type name is a variable in the AST, // Too much trouble to build assert (scope !=NULL); // This does not work //SgFunctionSymbol* func_sym = lookupFunctionSymbolInParentScopes(SgName("sizeof"), scope); SgGlobal* gscope = getGlobalScope (scope); assert (gscope !=NULL); SgFunctionSymbol* func_sym = gscope->lookup_function_symbol(SgName("sizeof")); assert (func_sym!=NULL); SgVarRefExp* type_var = buildVarRefExp( t->unparseToString(), scope ); assert (type_var !=NULL); sizeof_exp = buildFunctionCallExp (func_sym, buildExprListExp(type_var)); #else // sizeof is not an operator in Fortran, there is no unparsing support for this // sizeof_exp = buildSizeOfOp(t); // Directly obtain an integer size value sizeof_exp = buildIntVal(getSizeOf(t)); #endif } else if (is_C_language() || is_C99_language() || is_Cxx_language()) { sizeof_exp = buildSizeOfOp(t); } else { cerr<<"Error in calculateBytes(). Unsupported programming language other than C/Cxx and Fortran. "<<endl; assert (false); } SgExpression* mop = buildMultiplyOp(buildIntVal(count), sizeof_exp); if (result == NULL) result = mop; else result = buildAddOp(result, mop); } return result; }
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); }