MySynthesizedAttribute MyTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { MySynthesizedAttribute returnAttribute; switch(astNode->variantT()) { case V_SgVarRefExp: { cout << " found V_SgVarRefExp " << astNode->unparseToString() << endl; if(mReplaceVariable) { if( ( strcmp( astNode->unparseToString().c_str(), VARIABLE_NAME )==0 ) && ( isSgTypeInt(isSgVarRefExp(astNode)->get_type()) ) ) { returnAttribute.setVarRefFound( true ); AstRestructure::unparserReplace( isSgVarRefExp(astNode), "newInt" ); cout << " replacing with 'newInt' " << endl; } } } break; case V_SgVariableDeclaration: { SgVariableDeclaration *varDecl = isSgVariableDeclaration(astNode); cout << " found V_SgVariableDeclaration " << astNode->unparseToString() << endl; // replace only integer variables called "i" if( (varDecl->get_traversalSuccessorContainer().size() > 0) && isSgInitializedName( varDecl->get_traversalSuccessorContainer()[0]) && ( strcmp(isSgInitializedName(varDecl->get_traversalSuccessorContainer()[0])->get_name().str(), VARIABLE_NAME )==0 ) && ( isSgTypeInt(isSgInitializedName(varDecl->get_traversalSuccessorContainer()[0])->get_type()) ) ) { // found declaration of "int i" string newDeclaration("int newInt = i + 100;"); returnAttribute.insert( varDecl, newDeclaration, HighLevelCollectionTypedefs::LocalScope, HighLevelCollectionTypedefs::AfterCurrentPosition ); assert( mReplaceVariable==0 ); // if it's true, there is another "int i", and this transformation wont work... mReplaceVariable = 1; cout << " inserted: '" << newDeclaration <<"' , starting variable replacement " << endl; } } break; default: break; } // node type bool synth = false; for( SubTreeSynthesizedAttributes::iterator i=synthesizedAttributeList.begin(); i!= synthesizedAttributeList.end(); i++ ) { if( (*i).getVarRefFound() ) synth = true; } if( synth ) { returnAttribute.setVarRefFound( true ); if(isSgStatement( astNode )) { cout << " new statement " << " : '" << astNode->unparseToString() << "' " << endl; returnAttribute.setVarRefFound( false ); //if(!isSgReturnStmt( astNode )) { // DEBUG, this should work!??!? returnAttribute.replace( astNode, astNode->unparseToString(), HighLevelCollectionTypedefs::LocalScope ); //} } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable--; cerr << "end of scope " << mReplaceVariable << endl; } } return returnAttribute; }
MySynthesizedAttribute MyTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { MySynthesizedAttribute returnAttribute; switch(astNode->variantT()) { case V_SgForStatement: { SgForStatement *forStat = isSgForStatement(astNode); cout << " found V_SgForStatement " << printPosition(astNode) << "" << endl; for(size_t i=0; i<mAllFors.size(); i++) { if((mAllFors[i]->blocked)&&(astNode == mAllFors[i]->forStmt)) { ostringstream newFor; newFor << "for("; newFor << (*(forStat->get_init_stmt().begin()))->unparseToString(); newFor << forStat->get_test_expr()->unparseToString() << ";" ; newFor << mAllFors[i]->varName << "+=" << mAllFors[i]->blockSize << ")\n" ; newFor << forStat->get_loop_body()->unparseToString(); cout << " is blocked loop..." << endl; returnAttribute.replace( astNode, newFor.str() ); } } } break; case V_SgVarRefExp: { cout << " found V_SgVarRefExp " << printPosition(astNode) << astNode->unparseToString() << endl; forBlockVector fors = inheritedAttribute.getForScopes(); // replace variable occurrences in the loop kernel if(inheritedAttribute.getLoopKernel()) { for(size_t i=0;i<fors.size(); i++) { if( ( strcmp( astNode->unparseToString().c_str(), fors[i]->varName.c_str() )==0 ) && ( isSgVarRefExp(astNode)->get_type() == fors[i]->varType ) ) { string blockedVarName("blocked_"); blockedVarName += fors[i]->varName; AstRestructure::unparserReplace( isSgVarRefExp(astNode), blockedVarName ); cout << " replacing with '"<<blockedVarName<<"' " << endl; } } } } break; default: break; } // node type bool synth = false; for( SubTreeSynthesizedAttributes::iterator i=synthesizedAttributeList.begin(); i!= synthesizedAttributeList.end(); i++ ) { if( (*i).getVarRefFound() ) synth = true; } if( synth ) { returnAttribute.setVarRefFound( true ); if(isSgStatement( astNode )) { cout << " new statement " << printPosition(astNode) << " : '" << astNode->unparseToString() << "' " << endl; returnAttribute.setVarRefFound( false ); //if(!isSgReturnStmt( astNode )) { // DEBUG, this should work!??!? returnAttribute.replace( astNode, astNode->unparseToString(), HighLevelCollectionTypedefs::LocalScope ); //} } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable--; cerr << "end of scope " << mReplaceVariable << endl; } } //if(astNode == mpLoopBody) { // FIXME why doesnt replace basic block work? if( (astNode->get_parent() == mpLoopBody)&&(inheritedAttribute.getLoopKernel()) ) { // we're back at the loop kernel block, now replace and insert new loops... insertTransformedLoopBody( astNode, returnAttribute, inheritedAttribute.getForScopes() ); } return returnAttribute; }
/** * Const-qualify immutable objects * * \todo count assignments, if only one, report violation */ bool DCL00_C(const SgNode *node ) { const SgInitializedName *varName = isSgInitializedName(node); if (!varName) return false; /** * Ignore variables generated by macros */ if ((varName->get_name().getString().substr(0,2) == "__") || isCompilerGeneratedNode(node)) return false; /** * Ignore global variables */ if (isGlobalVar(varName)) return false; /** * Ignore variables that are already const, are function pointers, or are * declared inside of a struct, enum, or as an argument to a function */ SgType *varType = varName->get_type(); if (isConstType(varType) || isConstType(varType->dereference()) || isConstType(varType->dereference()->dereference()) || isSgFunctionType(varType) || isSgClassType(varType) || findParentOfType(varName, SgCtorInitializerList) || findParentOfType(varName, SgEnumDeclaration) || findParentOfType(varName, SgClassDeclaration)) return false; /** * DCL13-C is a subset of this rule, figure out which rule we are dealing * with here */ std::string ruleStr; std::string errStr; if (findParentOfType(varName, SgFunctionParameterList)) { /** ignore function prototypes, just worry about the definitions */ const SgFunctionDeclaration *fnDecl = findParentOfType(varName, SgFunctionDeclaration); /** * Disabling assertion due to C++ code */ if (!fnDecl) return false; // assert(fnDecl); if (!fnDecl->get_definition()) return false; if (isSgPointerType(varName->get_type()) || isSgArrayType(varName->get_type())) { ruleStr = "DCL13-C"; errStr = "Declare function parameters that are pointers to values not changed by the function as const: "; } else { return false; } } else { ruleStr = "DCL00-C"; errStr = "Const-qualify immutable objects: "; } /** * Ignore global variables or variables declared as extern */ const SgScopeStatement *varScope = varName->get_scope(); if (isSgGlobal(varScope) || isExternVar(varName)) return false; FOREACH_SUBNODE(varScope, nodes, i, V_SgVarRefExp) { const SgVarRefExp *iVar = isSgVarRefExp(*i); assert(iVar); if (getRefDecl(iVar) != varName) continue; const SgNode *parent = iVar->get_parent(); while (isSgCastExp(parent)) { parent = parent->get_parent(); } assert(parent); /** * If the variable is written to or it's address is taken, we can no * longer be sure it should be const, if it's a struct and gets * dereferenced, who knows what's getting written there :/ */ if (varWrittenTo(iVar) || isSgArrowExp(parent) || findParentOfType(iVar, SgAddressOfOp)) return false; /** * If the variable is a pointer or array, and we pass it to a function * or as an argument to pointer arithmetic, or assign it's value * somewhere, we can longer be sure it should be const */ if ((isSgPointerType(varType) || isSgArrayType(varType)) && (findParentOfType(iVar, SgFunctionCallExp) || isSgAddOp(parent) || isSgSubtractOp(parent) || isSgAssignOp(parent) || isSgPntrArrRefExp(parent) || isSgPointerDerefExp(parent) || isSgAssignInitializer(parent))) return false; } const std::string msg = errStr + varName->get_name().getString(); print_error(node, ruleStr.c_str(), msg.c_str(), true); return true; }
// Functions required by the tree traversal mechanism MyInheritedAttribute MyTraversal::evaluateRewriteInheritedAttribute ( SgNode* astNode, MyInheritedAttribute inheritedAttribute ) { MyInheritedAttribute returnAttribute = inheritedAttribute; switch(astNode->variantT()) { case V_SgForStatement: { cout << " found V_SgForStatement " << printPosition(astNode) << "" << endl; SgForStatement *forStat = isSgForStatement(astNode); forBlockInfo *inf = new forBlockInfo; inf->forStmt = forStat; SgInitializedName *varin = isSgInitializedName( forStat->get_traversalSuccessorContainer()[0] //for init ->get_traversalSuccessorContainer()[0] // var decl ->get_traversalSuccessorContainer()[0] // initialized name ); assert( varin ); inf->varName = varin->get_name().str(); inf->varType = varin->get_type(); inf->blocked = false; inf->blockSize = 0; returnAttribute.addForStatement( inf ); mAllFors.push_back( inf ); list<SgNode*> forList = NodeQuery::querySubTree( astNode, forStatementNodeQuery ); if( (forList.size()==1) && // only the current loop? (returnAttribute.getForScopes().size()>1) ) { cerr << " it is the innermost for loop " << endl; mpLoopBody = forStat->get_loop_body(); } } break; default: break; } if(astNode == mpLoopBody) { bool loopsValid = true; // do some basic checks for validity forBlockVector fors = returnAttribute.getForScopes(); for(size_t i=0;i<fors.size(); i++) { SgExpression *testExpr = fors[i]->forStmt->get_test_expr(); SgExpression *incExpr = fors[i]->forStmt->get_increment_expr(); if(isSgPlusPlusOp(incExpr) ==NULL) loopsValid = false; if(isSgLessThanOp(testExpr) ==NULL) loopsValid = false; else { if(! isSgVarRefExp(isSgLessThanOp(testExpr)->get_lhs_operand()) ) loopsValid = false; } } // this is the basic block of the innermost loop // only do trafos, if more than two nested loop nests, and we found the inner one if(loopsValid) { returnAttribute.setLoopKernel( true ); } else { cout << " loop nest not valid, skipping transformation..." << endl; } } if(isSgScopeStatement(astNode)) { // dont replace variable in higher scopes... if(mReplaceVariable > 0) { mReplaceVariable++; cerr << "nested scope found, #" << mReplaceVariable << endl; } } return returnAttribute; }
SgExpression * translateConstExpression( SgExpression * expr, const std::map<SgVariableSymbol *, SgVariableSymbol *> & param_to_local, const std::map<SgVariableSymbol *, SgVariableSymbol *> & iter_to_local ) { SgExpression * result = SageInterface::copyExpression(expr); std::map<SgVariableSymbol *, SgVariableSymbol *>::const_iterator it_sym_to_local; if (isSgVarRefExp(result)) { // Catch an issue when reading looptree from file. In this case, 'expr' may not have a valid parent. // If 'expr' is a SgVarRefExp, it causes an assertion to fail in SageInterface::replaceExpression SgVarRefExp * var_ref = (SgVarRefExp *)result; SgVariableSymbol * var_sym = var_ref->get_symbol(); SgVariableSymbol * local_sym = NULL; it_sym_to_local = param_to_local.find(var_sym); if (it_sym_to_local != param_to_local.end()) local_sym = it_sym_to_local->second; it_sym_to_local = iter_to_local.find(var_sym); if (it_sym_to_local != iter_to_local.end()) { assert(local_sym == NULL); // implies VarRef to a variable symbol which is both parameter and iterator... It does not make sense! local_sym = it_sym_to_local->second; } assert(local_sym != NULL); // implies VarRef to an unknown variable symbol (neither parameter or iterator) return SageBuilder::buildVarRefExp(local_sym); } std::vector<SgVarRefExp *> var_refs = SageInterface::querySubTree<SgVarRefExp>(result); std::vector<SgVarRefExp *>::const_iterator it_var_ref; for (it_var_ref = var_refs.begin(); it_var_ref != var_refs.end(); it_var_ref++) { SgVarRefExp * var_ref = *it_var_ref; SgVariableSymbol * var_sym = var_ref->get_symbol(); SgVariableSymbol * local_sym = NULL; it_sym_to_local = param_to_local.find(var_sym); if (it_sym_to_local != param_to_local.end()) local_sym = it_sym_to_local->second; it_sym_to_local = iter_to_local.find(var_sym); if (it_sym_to_local != iter_to_local.end()) { assert(local_sym == NULL); // implies VarRef to a variable symbol which is both parameter and iterator... It does not make sense! local_sym = it_sym_to_local->second; } assert(local_sym != NULL); // implies VarRef to an unknown variable symbol (neither parameter or iterator) SageInterface::replaceExpression(var_ref, SageBuilder::buildVarRefExp(local_sym), true); } return result; }
std::string writeSgBinaryOpZ3(SgBinaryOp* op, SgExpression* lhs, SgExpression* rhs) { std::stringstream ss; std::string opStr; bool compAssign = false; if (isSgCompoundAssignOp(op)) { compAssign = true; opStr = getSgCompoundAssignOp(isSgCompoundAssignOp(op)); } else { opStr = getSgBinaryOp(op); } ROSE_ASSERT(opStr != "unknown"); std::string rhsstring; std::string lhsstring; lhsstring = getSgExpressionString(lhs); SgType* lhstyp; SgType* rhstyp; if (isSgArrayType(lhs->get_type())) { lhstyp = isSgArrayType(lhs->get_type())->get_base_type(); } else { lhstyp = lhs->get_type(); } if (isSgArrayType(rhs->get_type())) { rhstyp = isSgArrayType(rhs->get_type())->get_base_type(); } else { rhstyp = rhs->get_type(); } if (isSgEnumType(lhs->get_type())) { } else { ROSE_ASSERT(lhstyp == rhstyp); } if (isSgValueExp(rhs)) { rhsstring = getSgValueExp(isSgValueExp(rhs)); } else if (isSgUnaryOp(rhs)) { rhsstring = getSgUnaryOp(isSgUnaryOp(rhs)); } else { rhsstring = getSgExpressionString(rhs); } if (opStr == "/" && lhstyp->isIntegerType()) { opStr = "cdiv"; } if (opStr == "assign" || compAssign) { if (isSgVarRefExp(lhs)) { SgVarRefExp* lhsSgVarRefExp = isSgVarRefExp(lhs); int instances = SymbolToInstances[lhsSgVarRefExp->get_symbol()]; std::stringstream instanceName; SymbolToInstances[lhsSgVarRefExp->get_symbol()] = instances + 1; std::string lhsname = SymbolToZ3[lhsSgVarRefExp->get_symbol()]; instanceName << lhsname << "_" << (instances+1); SgType* varType = lhsSgVarRefExp->get_type(); std::string typeZ3; if (varType->isFloatType()) { typeZ3 = "Real"; } else if (varType->isIntegerType()) { typeZ3 = "Int"; } else if (isSgEnumType(varType)) { typeZ3 = isSgEnumType(varType)->get_name().getString(); } else { typeZ3 = "Unknown"; } ss << "(declare-fun " << instanceName.str() << " () " << typeZ3 << ")\n"; if (!compAssign) { ss << "(assert (= " << instanceName.str() << " " << rhsstring << "))"; } else { std::stringstream oldInstanceName; oldInstanceName << lhsname << "_" << instances; ss << "(assert (= " << instanceName.str() << " (" << opStr << " " << oldInstanceName.str() << " " << rhsstring << ")))"; } } else { ROSE_ASSERT(isSgPntrArrRefExp(lhs)); std::string u_type; SgPntrArrRefExp* lhspntr = isSgPntrArrRefExp(lhs); SgVarRefExp* varlhspntr = isSgVarRefExp(lhspntr->get_lhs_operand()); SgArrayType* arrTy = isSgArrayType(varlhspntr->get_type()); if (arrTy->get_base_type()->isIntegerType()) { u_type = "Int"; } else if (arrTy->get_base_type()->isFloatType()) { u_type = "Real"; } else { std::cout << "unknown base type for array" << std::endl; ROSE_ASSERT(false); } std::stringstream oldInstanceName; SgVarRefExp* varexp = isSgVarRefExp((isSgPntrArrRefExp(lhs))->get_lhs_operand()); oldInstanceName << SymbolToZ3[varexp->get_symbol()] << "_" << SymbolToInstances[varexp->get_symbol()]; int instances = SymbolToInstances[varexp->get_symbol()]; std::stringstream instanceName; SymbolToInstances[varexp->get_symbol()] = instances + 1; std::string lhsname = SymbolToZ3[varexp->get_symbol()]; instanceName << lhsname << "_" << instances+1; ss << "(declare-const " << instanceName.str() << " (Array Int " << u_type << "))\n "; std::string indexstring = getSgExpressionString(isSgPntrArrRefExp(lhs)->get_rhs_operand()); ss << "(assert (= (store " << oldInstanceName.str() << " " << indexstring << " " << rhsstring << ") " << instanceName.str() << "))"; } } else if (opStr == "neq") { ss << "(not (= " << lhsstring << " " << rhsstring << "))"; } else if (opStr == "or" || opStr == "and") { std::stringstream val_stream; if (pathNodeTruthValue.find(op) != pathNodeTruthValue.end()) { bool logic_val = pathNodeTruthValue[op]; //std::cout << ";and/or lhsstring " << lhsstring << "\n"; //std::cout << ";and/or rhsstring " << rhsstring << "\n"; if (opStr == "and") { if (logic_val) { std::string p_decl = "(assert (= " + lhsstring + " true))"; declarations.push_back(p_decl); ss << rhsstring; //ss << "(and " << lhsstring << " " << rhsstring << ")"; } else { std::string p_decl = "(assert (= " + lhsstring + " false))"; declarations.push_back(p_decl); ss << "false"; } } else { if (logic_val) { std::string p_decl = "(assert (= " + lhsstring + " true))"; declarations.push_back(p_decl); ss << "true"; } else { std::string p_decl = "(assert (= " + lhsstring + " false))"; declarations.push_back(p_decl); ss << rhsstring; } } } else { ss << ""; } } else { ss << "(" << opStr << " " << lhsstring << " " << rhsstring << ")"; } return ss.str(); }
std::string getSgExpressionString(SgExpression* expNode) { //bool returnString = false; std::string expString; bool set_to_expression_val = false; VariantT var = expNode->variantT(); if (isSgBinaryOp(expNode)) { SgBinaryOp* binOp = isSgBinaryOp(expNode); SgExpression* lhs_exp = binOp->get_lhs_operand(); SgExpression* rhs_exp = binOp->get_rhs_operand(); expString = writeSgBinaryOpZ3(binOp, lhs_exp, rhs_exp); if (isSgAssignOp(binOp) || isSgCompoundAssignOp(binOp)) { declarations.push_back(expString); expString = ""; } else if (isSgEqualityOp(binOp) || isSgGreaterThanOp(binOp) || isSgGreaterOrEqualOp(binOp) || isSgLessThanOp(binOp) || isSgLessOrEqualOp(binOp) || isSgNotEqualOp(binOp) || isSgAndOp(binOp) || isSgOrOp(binOp)) { //set_to_expression_val = true; } } else if (isSgUnaryOp(expNode)) { expString = getSgUnaryOp(isSgUnaryOp(expNode)); } else if (isSgValueExp(expNode)) { expString = getSgValueExp(isSgValueExp(expNode)); } else { switch (var) { case V_SgCallExpression: std::cout << "SgCallExpression not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgClassNameRefExp: std::cout << "SgClassNameRefExp not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgConditionalExp: std::cout << "SgConditionalExp (trinary A ? B : C) not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgExprListExp: std::cout << "SgExprListExp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgFunctionRefExp: std::cout << "SgFunctionRefExp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgDeleteExp: std::cout << "SgDeleteExp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgInitializer: std::cout << "SgInitializer is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgNaryOp: std::cout << "SgNaryOp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgNewExp: std::cout << "SgNewExp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgNullExpression: expString = "; null expression"; break; case V_SgRefExp: std::cout << "SgRefExp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgSizeOfOp: std::cout << "SgSizeOfOp is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgStatementExpression: std::cout << "SgStatementExpression is not yet implemented" << std::endl; expString = ""; ROSE_ASSERT(false); break; case V_SgValueExp: std::cout << "V_SgValueExp should never be encountered" << std::endl; ROSE_ASSERT(false); expString = ""; break; case V_SgVarRefExp: expString = getSgVarRefExp(isSgVarRefExp(expNode)); break; default: std::cout << expNode->class_name() << " is not being considered for implementation"; expString = ""; #ifndef VERBOSE_COMPLETE ROSE_ASSERT(false); #endif } } /*if (set_to_expression_val) { std::stringstream exp_var; exp_var << "e_" << expression_count; expression_count++; std::string exp_var_decl = "(declare-const " + exp_var.str() + " Bool)"; variables.push_back(exp_var_decl); std::string exp_var_val = "(assert (= " + exp_var.str() + " " + expString + "))"; expressions.push_back(exp_var_val); return exp_var.str(); } else { return expString; }*/ return expString; }
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); }