void examineType(SgType *type, ostream &out) { int nr_stars = 0; stringstream ss1; if (NULL == type) { out << "void"; return; } while (isSgArrayType(type) || isSgPointerType(type)) { if (isSgArrayType(type)) { SgArrayType *atype = isSgArrayType(type); SgExpression *expr = atype->get_index(); type = atype->get_base_type(); /* ss1 << "["; if (expr) examineExpr(expr, ss1); ss1 << "]"; */ nr_stars++; } else { SgPointerType *ttype = isSgPointerType(type); type = ttype->get_base_type(); nr_stars++; } } examinePrimTypeName(type, out); out << " "; for (int i = 0; i < nr_stars; ++i) out << "*"; out << ss1.str(); }
InheritedAttribute BugSeeding::evaluateInheritedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute ) { // Use this if we only want to seed bugs in loops bool isLoop = inheritedAttribute.isLoop || (isSgForStatement(astNode) != NULL) || (isSgWhileStmt(astNode) != NULL) || (isSgDoWhileStmt(astNode) != NULL); // Add Fortran support isLoop = isLoop || (isSgFortranDo(astNode) != NULL); // Mark future noes in this subtree as being part of a loop inheritedAttribute.isLoop = isLoop; // To test this on simple codes, optionally allow it to be applied everywhere bool applyEveryWhere = true; if (isLoop == true || applyEveryWhere == true) { // The inherited attribute is true iff we are inside a loop and this is a SgPntrArrRefExp. SgPntrArrRefExp *arrayReference = isSgPntrArrRefExp(astNode); if (arrayReference != NULL) { // Mark as a vulnerability inheritedAttribute.isVulnerability = true; // Now change the array index (to seed the buffer overflow bug) SgVarRefExp* arrayVarRef = isSgVarRefExp(arrayReference->get_lhs_operand()); ROSE_ASSERT(arrayVarRef != NULL); ROSE_ASSERT(arrayVarRef->get_symbol() != NULL); SgInitializedName* arrayName = isSgInitializedName(arrayVarRef->get_symbol()->get_declaration()); ROSE_ASSERT(arrayName != NULL); SgArrayType* arrayType = isSgArrayType(arrayName->get_type()); ROSE_ASSERT(arrayType != NULL); SgExpression* arraySize = arrayType->get_index(); SgTreeCopy copyHelp; // Make a copy of the expression used to hold the array size in the array declaration. SgExpression* arraySizeCopy = isSgExpression(arraySize->copy(copyHelp)); ROSE_ASSERT(arraySizeCopy != NULL); // This is the existing index expression SgExpression* indexExpression = arrayReference->get_rhs_operand(); ROSE_ASSERT(indexExpression != NULL); // Build a new expression: "array[n]" --> "array[n+arraySizeCopy]", where the arraySizeCopy is a size of "array" SgExpression* newIndexExpression = buildAddOp(indexExpression,arraySizeCopy); // Substitute the new expression for the old expression arrayReference->set_rhs_operand(newIndexExpression); } } return inheritedAttribute; }
SgType* Fortran_to_C::translateType(SgType* oldType) { switch(oldType->variantT()) { case V_SgTypeString: { SgExpression* stringLength = deepCopy(isSgTypeString(oldType)->get_lengthExpression()); SgArrayType* newType = buildArrayType(buildCharType(),NULL); newType->set_rank(1); newType->set_dim_info(buildExprListExp(stringLength)); return newType; } case V_SgTypeFloat: { SgIntVal* typeKind = isSgIntVal(oldType->get_type_kind()); if(typeKind == NULL) { // TODO: we just return original type. Might need to fix this in the future return oldType; } switch(typeKind->get_value()) { case 4: return buildFloatType(); case 8: return buildDoubleType(); default: ROSE_ASSERT(false); } } case V_SgTypeInt: { SgIntVal* typeKind = isSgIntVal(oldType->get_type_kind()); if(typeKind == NULL) { // TODO: we just return original type. Might need to fix this in the future return oldType; } switch(typeKind->get_value()) { case 2: return buildShortType(); case 4: return buildIntType(); case 8: return buildLongType(); default: ROSE_ASSERT(false); } } default: return oldType; } }
/** * class: SgArrayType * term: array_type(nested,index) * arg nested: nested type * arg index: index (a SgExpression) */ PrologCompTerm* RoseToTerm::getArrayTypeSpecific(SgType* mtype) { /*make sure we are actually dealing with an array type*/ SgArrayType* a = isSgArrayType(mtype); ROSE_ASSERT(a != NULL); return new PrologCompTerm ("array_type", //2, getTypeSpecific(a->get_base_type()), /* get nested type*/ (a->get_index() /* get expression*/ ? traverseSingleNode(a->get_index()) : new PrologAtom("null"))); }
void examineInitializedName(SgInitializedName *name, ostream &out) { SgSymbol* symbol = name->get_symbol_from_symbol_table(); if (NULL == symbol) return; SgType *type = symbol->get_type(); int nr_stars = 0; stringstream ss1; while (isSgArrayType(type) || isSgPointerType(type)) { if (isSgArrayType(type)) { SgArrayType *atype = isSgArrayType(type); SgExpression *expr = atype->get_index(); type = atype->get_base_type(); ss1 << "["; if (expr) examineExpr(expr, ss1); ss1 << "]"; } else { SgPointerType *ttype = isSgPointerType(type); type = ttype->get_base_type(); nr_stars++; } } examinePrimTypeName(type, out); out << " "; for (int i = 0; i < nr_stars; ++i) out << "*"; out << symbol->get_name().getString(); out << ss1.str(); SgInitializer *initer = name->get_initializer(); if (initer) { switch (initer->variantT()) { case V_SgAssignInitializer: SgAssignInitializer *ai = isSgAssignInitializer(initer); SgExpression *expr = ai->get_operand(); if (expr) { out << "="; examineExpr(expr, out); } break; default: break; } } }
void DetectHiddenOriginalExpressionTreeTraversal::visit ( SgNode* node ) { // We only want to search for original expression trees where they can be hidden. ROSE_ASSERT(node != NULL); SgArrayType* arrayType = isSgArrayType(node); if (arrayType != NULL) { #if 0 printf ("Found an array type arrayType = %p (looking for original expression tree) \n",arrayType); #endif SgExpression* index = arrayType->get_index(); if (index != NULL) { DetectOriginalExpressionTreeTraversal t; t.traverse(index,preorder); } } #if 0 // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression. SgVariableDefinition* variableDefinition = isSgVariableDefinition(node); if (variableDefinition != NULL) { #if 0 printf ("Found a SgVariableDefinition (looking for original expression tree) \n"); #endif SgExpression* bitfieldExp = variableDefinition->get_bitfield(); if (bitfieldExp != NULL) { DetectOriginalExpressionTreeTraversal t; t.traverse(bitfieldExp,preorder); } } #endif }
void basetype(ExprSynAttr *a) { stringstream ts; if (NULL == a) return; switch (a->sgtype->variantT()) { case V_SgArrayType: { SgArrayType *atype = isSgArrayType(a->sgtype); sgtype = atype->get_base_type(); break; } case V_SgPointerType: { SgPointerType *ptype = isSgPointerType(a->sgtype); sgtype = ptype->get_base_type(); break; } default: sgtype = a->sgtype; } examineType(sgtype, ts); type = ts.str(); }
InheritedAttribute visitorTraversal::evaluateInheritedAttribute(SgNode* n, InheritedAttribute inheritedAttribute) { Sg_File_Info* s = n->get_startOfConstruct(); Sg_File_Info* e = n->get_endOfConstruct(); Sg_File_Info* f = n->get_file_info(); for(int x=0; x < inheritedAttribute.depth; ++x) { printf(" "); } if(s != NULL && e != NULL && !isSgLabelStatement(n)) { printf ("%s (%d, %d, %d)->(%d, %d): %s",n->sage_class_name(),s->get_file_id()+1,s->get_raw_line(),s->get_raw_col(),e->get_raw_line(),e->get_raw_col(), verbose ? n->unparseToString().c_str() : "" ); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } SgExprStatement * exprStmt = isSgExprStatement(n); if(exprStmt != NULL) { printf(" [expr type: %s]", exprStmt->get_expression()->sage_class_name()); SgFunctionCallExp * fcall = isSgFunctionCallExp(exprStmt->get_expression()); if(fcall != NULL) { SgExpression * funcExpr = fcall->get_function(); if(funcExpr != NULL) { printf(" [function expr: %s]", funcExpr->class_name().c_str()); } SgFunctionDeclaration * fdecl = fcall->getAssociatedFunctionDeclaration(); if(fdecl != NULL) { printf(" [called function: %s]", fdecl->get_name().str()); } } } if(isSgFunctionDeclaration(n)) { printf(" [declares function: %s]", isSgFunctionDeclaration(n)->get_name().str()); } SgStatement * sgStmt = isSgStatement(n); if(sgStmt != NULL) { printf(" [scope: %s, %p]", sgStmt->get_scope()->sage_class_name(), sgStmt->get_scope()); } //SgLabelStatement * lblStmt = isSgLabelStatement(n); //if(lblStmt != NULL) { // SgStatement * lblStmt2 = lblStmt->get_statement(); //} } else if (f != NULL) { SgInitializedName * iname = isSgInitializedName(n); if(iname != NULL) { SgType* inameType = iname->get_type(); printf("%s (%d, %d, %d): %s [type: %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(),n->unparseToString().c_str(),inameType->class_name().c_str()); SgDeclarationStatement * ds = isSgDeclarationStatement(iname->get_parent()); if(ds != NULL) { if(ds->get_declarationModifier().get_storageModifier().isStatic()) { printf(" static"); } } SgArrayType * art = isSgArrayType(iname->get_type()); if(art != NULL) { printf(" %d", art->get_rank()); } printf("]"); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } else { printf("%s (%d, %d, %d): %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(), verbose ? n->unparseToString().c_str() : ""); } } else { printf("%s : %s", n->sage_class_name(), verbose ? n->unparseToString().c_str() : ""); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } printf(" succ# %lu", n->get_numberOfTraversalSuccessors()); printf("\n"); return InheritedAttribute(inheritedAttribute.depth+1); }
void RemoveConstantFoldedValueViaParent::visit ( SgNode* node ) { // This is an alternative implementation that allows us to handle expression that are not // traversed in the AST (e.g. types like SgArrayType which can contain expressions). ROSE_ASSERT(node != NULL); // DQ (3/11/2006): Set NULL pointers where we would like to have none. #if 0 printf ("In RemoveConstantFoldedValueViaParent::visit(): node = %p = %s \n",node,node->class_name().c_str()); #endif // DQ (10/12/2012): Turn this on so that we can detect failing IR nodes (failing later) that have valid originalExpressionTrees. // DQ (10/12/2012): Turn this back off because it appears to fail... #if 0 SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { SgNode* parent = exp->get_parent(); if (parent != NULL) { printf ("Current IR node with SgExpression parent = %p = %s child = %p = %s originalExpressionTree = %p = %s \n",parent,parent->class_name().c_str(),node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); bool traceReplacement = true; ConstantFoldedValueReplacer r(traceReplacement, exp); parent->processDataMemberReferenceToPointers(&r); // node->processDataMemberReferenceToPointers(&r); } // Set the originalExpressionTree to NULL. exp->set_originalExpressionTree(NULL); // Set the parent of originalExpressionTree to be the parent of exp. originalExpressionTree->set_parent(parent); // And then delete the folded constant. SageInterface::deleteAST(exp); } } #endif SgArrayType* arrayType = isSgArrayType(node); if (arrayType != NULL) { #if 0 printf ("Found an array type arrayType = %p arrayType->get_index() = %p \n",arrayType,arrayType->get_index()); #endif SgExpression* index = arrayType->get_index(); if (index != NULL) { #if 0 printf ("Fixup array index = %p = %s (traverse index AST subtree) \n",index,index->class_name().c_str()); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(index); #if 0 printf ("DONE: Fixup array index = %p (traverse index AST) \n\n\n\n",index); #endif #if 0 printf ("Found an array index = %p (fixup index directly) \n",index); #endif // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = index->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Found an originalExpressionTree in the array index originalExpressionTree = %p \n",originalExpressionTree); #endif // DQ (6/12/2013): This appears to be a problem in EDG 4.7 (see test2011_117.C). std::vector<SgExpression*> redundantChainOfOriginalExpressionTrees; if (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Detected originalExpressionTree nested directly within the originalExpressionTree \n", originalExpressionTree,originalExpressionTree->class_name().c_str(), originalExpressionTree->get_originalExpressionTree(),originalExpressionTree->get_originalExpressionTree()->class_name().c_str()); #endif // Loop to the end of the chain of original expressions (which EDG 4.7 should never have constructed). while (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Looping through a chain of originalExpressionTrees \n"); #endif // Save the list of redundnat nodes so that we can delete them properly. redundantChainOfOriginalExpressionTrees.push_back(originalExpressionTree); originalExpressionTree = originalExpressionTree->get_originalExpressionTree(); } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } arrayType->set_index(originalExpressionTree); originalExpressionTree->set_parent(arrayType); index->set_originalExpressionTree(NULL); // printf ("DEBUGING: skip delete of index in array type \n"); delete index; // DQ (6/12/2013): Delete the nodes that we had to skip over (caused by chain of redundant entries from EDG 4.7). std::vector<SgExpression*>::iterator i = redundantChainOfOriginalExpressionTrees.begin(); while (i != redundantChainOfOriginalExpressionTrees.end()) { #if 0 printf ("deleting the redundnat originalExpressionTree chain caused by EDG 4.7 (delete %p = %s) \n",*i,(*i)->class_name().c_str()); #endif delete *i; i++; } index = NULL; } } } SgVariableDefinition* variableDefinition = isSgVariableDefinition(node); if (variableDefinition != NULL) { #if 0 printf ("Found a SgVariableDefinition \n"); #endif SgExpression* bitfieldExp = variableDefinition->get_bitfield(); if (bitfieldExp != NULL) { #if 0 printf ("Fixup bitfieldExp = %p (traverse bitfieldExp AST subtree) \n",bitfieldExp); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(bitfieldExp); // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = bitfieldExp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression. variableDefinition->set_bitfield(originalExpressionTree); originalExpressionTree->set_parent(variableDefinition); bitfieldExp->set_originalExpressionTree(NULL); delete bitfieldExp; bitfieldExp = NULL; #else // The ROSE AST needs to be fixed to handle more general expressions for bitfield widths (this does not effect the CFG). // TODO: Change the data type of the bitfield data member in SgVariableDefinition. // DQ (1/20/2014): This has been done now. // printf ("Member data bitfield widths need to be changed (in the ROSE IR) to support more general expressions (can't fix this original expression tree) \n"); #endif #if 0 // This case is not handled yet! printf ("Found an original expression tree in a bitfield expression \n"); ROSE_ASSERT(false); #endif } } } }
void Fortran_to_C::linearizeArraySubscript(SgPntrArrRefExp* pntrArrRefExp) { // get lhs operand SgVarRefExp* arrayName = isSgVarRefExp(pntrArrRefExp->get_lhs_operand()); // get array symbol SgVariableSymbol* arraySymbol = arrayName->get_symbol(); // get array type and dim_info SgArrayType* arrayType = isSgArrayType(arraySymbol->get_type()); ROSE_ASSERT(arrayType); SgExprListExp* dimInfo = arrayType->get_dim_info(); // get rhs operand SgExprListExp* arraySubscript = isSgExprListExp(pntrArrRefExp->get_rhs_operand()); /* No matter it is single or multi dimensional array, pntrArrRefExp always has a child, SgExprListExp, to store the subscript information. */ if(arrayType->findBaseType()->variantT() == V_SgTypeString) { arraySubscript->prepend_expression(buildIntVal(1)); } if(arraySubscript != NULL) { // get the list of subscript SgExpressionPtrList subscriptExprList = arraySubscript->get_expressions(); // get the list of dimension inforamtion from array definition. SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Create new SgExpressionPtrList for the linearalized array subscript. SgExpressionPtrList newSubscriptExprList; // rank info has to match between subscripts and dim_info ROSE_ASSERT(arraySubscript->get_expressions().size() == dimInfo->get_expressions().size()); /* The subscript conversion is following this example: case 1: dimension a(d1,d2,d3,d4) ====> dimension a(d1*d2*d3*d4) a(s1,s2,s3,s4) ====> a(s1-1 + d1*(s2-1 + d2*( s3-1 + d3*(s4-1)))) case 2: dimension a(d1L:d1H,d2L:d2H) ====> dimension a((d1H-d1L+1)*(d2H-d2L+1)) a(s1,s2) ====> a(s1-d1L + (d1H-d1L+1)*(s2-d2L)) */ Rose_STL_Container<SgExpression*>::reverse_iterator j1 = subscriptExprList.rbegin(); Rose_STL_Container<SgExpression*>::reverse_iterator j2 = dimExpressionPtrList.rbegin(); // Need to know current size of both current and previous dimension SgExpression* newSubscript; while((j1 != subscriptExprList.rend()) && (j2 != dimExpressionPtrList.rend())) { // get the lowerBound for each dimension SgExpression* newDimIndex; SgExpression* dimSize; /* get the dimension size at each dimension */ SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(*j2); /* This is for the 1st type of array declaration: a(10,15,20) Fortran is 1-based array. Lowerbound is 1 by default. */ if(subscriptExpression == NULL) { dimSize = deepCopy(*j2); } /* This is for the 2nd type of array declaration: a(1:10,5:15,10:20) Actual dimension size = upperBound - lowerBound + 1 */ else { dimSize = buildAddOp(buildSubtractOp(deepCopy(subscriptExpression->get_upperBound()), deepCopy(subscriptExpression->get_lowerBound())), buildIntVal(1)); } // convert the 1-based subscript to 0-based subscript newDimIndex = get0basedIndex(*j1, *j2); if(j1 != subscriptExprList.rbegin()) { newSubscript = buildAddOp(newDimIndex, buildMultiplyOp(dimSize,newSubscript)); } else { newSubscript = newDimIndex; delete(dimSize); } ++j1; ++j2; } // end of while loop newSubscriptExprList.push_back(newSubscript); SgExprListExp* newSubscriptList = buildExprListExp(newSubscriptExprList); // un-link and remove the rhs operand pntrArrRefExp->get_rhs_operand()->set_parent(NULL); removeList.push_back(pntrArrRefExp->get_rhs_operand()); // add the new subscriptExpression into rhs operand pntrArrRefExp->set_rhs_operand(newSubscriptList); newSubscriptList->set_parent(pntrArrRefExp); } // end of arraySubscript != NULL }
void Fortran_to_C::translateArraySubscript(SgPntrArrRefExp* pntrArrRefExp) { // get lhs operand SgVarRefExp* arrayName = isSgVarRefExp(pntrArrRefExp->get_lhs_operand()); SgExpression* baseExp = isSgExpression(arrayName); // get array symbol SgVariableSymbol* arraySymbol = arrayName->get_symbol(); // get array type and dim_info SgArrayType* arrayType = isSgArrayType(arraySymbol->get_type()); ROSE_ASSERT(arrayType); SgExprListExp* dimInfo = arrayType->get_dim_info(); // get rhs operand SgExprListExp* arraySubscript = isSgExprListExp(pntrArrRefExp->get_rhs_operand()); if(arrayType->findBaseType()->variantT() == V_SgTypeString) { arraySubscript->prepend_expression(buildIntVal(1)); } /* No matter it is single or multi dimensional array, pntrArrRefExp always has a child, SgExprListExp, to store the subscript information. */ if(arraySubscript != NULL) { // get the list of subscript SgExpressionPtrList subscriptExprList = arraySubscript->get_expressions(); // get the list of dimension inforamtion from array definition. SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Create new SgExpressionPtrList for the linearalized array subscript. SgExpressionPtrList newSubscriptExprList; // rank info has to match between subscripts and dim_info ROSE_ASSERT(arraySubscript->get_expressions().size() == dimInfo->get_expressions().size()); if(subscriptExprList.size() == 1) { Rose_STL_Container<SgExpression*>::iterator j1 = subscriptExprList.begin(); Rose_STL_Container<SgExpression*>::iterator j2 = dimExpressionPtrList.begin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_rhs_operand(newIndexExp); } else { Rose_STL_Container<SgExpression*>::reverse_iterator j1 = subscriptExprList.rbegin(); Rose_STL_Container<SgExpression*>::reverse_iterator j2 = dimExpressionPtrList.rbegin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); SgPntrArrRefExp* newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); j1 = j1 + 1; j2 = j2 + 1; for(; j1< (subscriptExprList.rend()-1); ++j1, ++j2) { SgExpression* newIndexExp = get0basedIndex(*j1, *j2); baseExp = isSgExpression(newPntrArrRefExp); newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); } newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_lhs_operand(newPntrArrRefExp); pntrArrRefExp->set_rhs_operand(newIndexExp); newIndexExp->set_parent(pntrArrRefExp); } } }
std::string initializeVariable(SgInitializedName* initName) { //if array type we need to get the index expression std::string index_expression_string; std::stringstream nameStringStream; SgName initNameName = initName->get_qualified_name(); SgSymbol* initNameSym = initName->search_for_symbol_from_symbol_table(); if (variablesOfNameX.find(initNameName.getString()) == variablesOfNameX.end()) { nameStringStream << initNameName.getString() << "_0"; variablesOfNameX[initNameName.getString()] = 1; } else { int occurrence = variablesOfNameX[initNameName.getString()]; nameStringStream << initNameName.getString() << "_" << occurrence; variablesOfNameX[initNameName.getString()] = occurrence+1; } SymbolToZ3[initNameSym] = nameStringStream.str(); SymbolToInstances[initNameSym] = 0; SgType* initNameType = initName->get_type(); std::string typeZ3; if (initNameType->isIntegerType()) { typeZ3 = "Int"; } else if (initNameType->isFloatType()) { typeZ3 = "Real"; } else if (isSgArrayType(initNameType)) { SgArrayType* arrTyp = isSgArrayType(initNameType); ROSE_ASSERT(arrTyp != NULL); SgType* underlying_type = arrTyp->get_base_type(); std::string array_typeZ3; if (underlying_type->isIntegerType()) { array_typeZ3 = "Int"; } else if (underlying_type->isFloatType()) { array_typeZ3 = "Real"; } else { std::cout << "unknown underlying type of array!" << std::endl; std::cout << underlying_type->class_name() << std::endl; ROSE_ASSERT(false); } SgExpression* ind = arrTyp->get_index(); std::stringstream arrStr; index_expression_string = getSgExpressionString(ind); typeZ3 = "(Array Int " + array_typeZ3 + ")"; } else if (isSgClassType(initNameType)) { std::cout << "structs are not yet implemented" << std::endl; ROSE_ASSERT(false); } else if (isSgPointerType(initNameType)) { std::cout << "pointers are not yet implemented" << std::endl; ROSE_ASSERT(false); } else if (isSgEnumType(initNameType)) { SgEnumType* et = isSgEnumType(initNameType); SgEnumDeclaration* enum_d = isSgEnumDeclaration(et->getAssociatedDeclaration()); getSgDeclarationStatement(enum_d); typeZ3 = et->get_name().getString(); } else { std::cout << "unknown type: " << initNameType->class_name() << std::endl; ROSE_ASSERT(false); } std::string name = nameStringStream.str() + "_0"; std::stringstream streamZ3; if (isSgArrayType(initNameType)) { streamZ3 << "(declare-const " << name << " " << typeZ3 << ")"; streamZ3 << "\n(declare-fun " << name << "_len () Int)"; streamZ3 << "\n(assert (= " << name << "_len " << index_expression_string << "))"; #ifdef ARRAY_TEST std::cout << "arrStream: " << streamZ3.str() << std::endl; #endif } else if (isSgEnumType(initNameType)) { streamZ3 << "(declare-const " << name << " " << typeZ3 << ")"; } else { streamZ3 << "(declare-fun " << name << " () " << typeZ3 << ")"; } return streamZ3.str(); }
ExprSynAttr *examineVariableDeclaration(SgVariableDeclaration* decl, ostream &out) { SgInitializedNamePtrList& name_list = decl->get_variables(); SgInitializedNamePtrList::const_iterator name_iter; ExprSynAttr *ret = NULL; ExprSynAttr *gc = NULL; ret = new ExprSynAttr(); for (name_iter = name_list.begin(); name_iter != name_list.end(); name_iter++) { SgInitializedName* name = *name_iter; SgSymbol* symbol = name->get_symbol_from_symbol_table(); SgType *type = symbol->get_type(); int nr_stars = 0; stringstream ss1; while (isSgArrayType(type) || isSgPointerType(type)) { if (isSgArrayType(type)) { SgArrayType *atype = isSgArrayType(type); SgExpression *expr = atype->get_index(); type = atype->get_base_type(); ss1 << "["; if (expr) examineExpr(expr, ss1); ss1 << "]"; } else { SgPointerType *ttype = isSgPointerType(type); type = ttype->get_base_type(); nr_stars++; } } examinePrimTypeName(type, ret->code); ret->code << " "; for (int i = 0; i < nr_stars; ++i) ret->code << "*"; ret->code << symbol->get_name().getString(); ret->code << ss1.str(); ss1.str(""); SgInitializer *initer = name->get_initializer(); if (initer) { switch (initer->variantT()) { case V_SgAssignInitializer: SgAssignInitializer *ai = isSgAssignInitializer(initer); SgExpression *expr = ai->get_operand(); if (expr) { ret->code << "="; gc = examineExpr(expr, ret->code); if (gc != NULL) delete gc; } break; default: break; } } /* end of this decl */ ret->code << ";"; out << ret->code.str(); return ret; /* cout << "[Decl] Variable (name:"<<symbol->get_name().getString(); cout << ",type:"<<symbol->get_type()->class_name(); cout << ",init:"; SgInitializer* init_expr = name->get_initializer(); if (init_expr) cout << init_expr->class_name(); else cout << "none"; cout << ")" << endl; */ } }
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(); }
string SIDL_TreeTraversal::generateSIDLFunctionDeclaration(SgFunctionDeclaration* functionDeclarationStatement ) { ROSE_ASSERT (functionDeclarationStatement != NULL); ROSE_ASSERT (functionDeclarationStatement->get_file_info() != NULL); const SgSpecialFunctionModifier &functionModifier = functionDeclarationStatement->get_specialFunctionModifier(); string functionName = functionDeclarationStatement->get_name().str(); string sidlFunctionName ; if (functionModifier.isConstructor()) { if (functionDeclarationStatement->get_args().size() == 0) return ""; // skip empty constructor sidlFunctionName = constructorName; } else { sidlFunctionName = functionName; } // We have to force the mangled name to be generated before we access it (else we just get "defaultName") string mangledFunctionName = functionDeclarationStatement->get_mangled_name().str(); sidlFunctionName = stringifyOperatorWithoutSymbols(sidlFunctionName); // Get the class name SgClassDefinition* classDefinition = isSgClassDefinition(functionDeclarationStatement->get_scope()); // DQ (1/7/2004): Modified for make EDG version 3.3 work (member function declarations's normalized by EDG) if (classDefinition != NULL) { SgClassDeclaration* classDeclaration = classDefinition->get_declaration(); string className = classDeclaration->get_name().str(); overloadInformation info = isOverloaded(classDefinition,functionName,mangledFunctionName); int orderofOverloadedFunction = info.get_order(); // If function is overloaded then append the number indicating the order of appearance in the // class declaration if (info.get_count() > 1) { vector<SgType*> types = info.get_types(); // SgInitializedNamePtrList &args = functionDeclarationStatement->get_args (); int size = types.size(); if(size > 0) { if(size < 3) { sidlFunctionName += "["; for(vector<SgType*>::iterator i = types.begin(); i!= types.end(); i++) { if(i != types.begin()) sidlFunctionName += "_"; if(isSgPointerType(*i) != NULL) sidlFunctionName += "P"; sidlFunctionName += sidlOverloadExtension(TransformationSupport::getTypeName(*i)); } sidlFunctionName += "]"; } else sidlFunctionName += "["+numberToOverloadString(orderofOverloadedFunction)+"]"; } } } else { printf ("EDG version 3.3 can return a null pointer to the member function definition \n"); } SgFunctionType* functionType = functionDeclarationStatement->get_type(); ROSE_ASSERT(functionType != NULL); // SgType* returnType = functionType->get_return_type(); // ROSE_ASSERT (returnType != NULL); // string returnTypeName = TransformationSupport::getTypeName(returnType); // printf ("function has_ellipses %s \n",(functionType->get_has_ellipses() != false) ? "true" : "false"); // showSgFunctionType(cout, functionType, "Called from generateSIDLFunctionDeclaration", 0 ); // printf ("Function return type = %s \n",returnTypeName.c_str()); #if 0 SgTypePtrList & argumentTypeList = functionType->get_arguments(); ROSE_ASSERT (argumentTypeList.size() >= 0); SgTypePtrList::iterator argumentIterator = argumentTypeList.begin(); for (argumentIterator = argumentTypeList.begin(); argumentIterator != argumentTypeList.end(); argumentIterator++) { // showSgType(os,(*argumentIterator), label, depth+1); string argumentTypeName = TransformationSupport::getTypeName(*argumentIterator); printf ("-----> argument #%d argumentTypeName = %s \n",argumentCounter++,argumentTypeName.c_str()); } #endif //Determine the SIDL parameter passing mechanism (in,out,inout) SgInitializedNamePtrList & argumentList = functionDeclarationStatement->get_args(); string parameterTypesAndNames; SgInitializedNamePtrList::iterator i; unsigned int argumentCounter = 0; for (i = argumentList.begin(); i != argumentList.end(); i++) { SgType* type = (*i)->get_type(); ROSE_ASSERT (type != NULL); string typeName = TransformationSupport::getTypeName(type); ROSE_ASSERT (typeName.c_str() != NULL); string sidlParameterPassingMechanim = "in"; //it seems like the has_ellipses value is wrong, so we'll set it functionType->set_has_ellipses(false); if(type->variantT() == V_SgTypeEllipse) { sidlParameterPassingMechanim = "inout"; functionType->set_has_ellipses(true); } //else if (type->variantT() == V_SgTypeVoid) /*else if (rose::stringDuplicate(type->sage_class_name()) == "SgTypeVoid") { printf("found a void\n"); //void type is only viable for a pointer. foo(void) will just become foo() if(isSgPointerType(type) != NULL) { printf("found a void pointer\n"); sidlParameterPassingMechanim ="inout opaque"; } }*/ else if (isSgReferenceType(type) != NULL) { sidlParameterPassingMechanim = "inout"; } else if (isSgPointerType(type) != NULL) { sidlParameterPassingMechanim = "inout"; } else if (isSgArrayType(type) != NULL) { SgArrayType array = isSgArrayType(type); sidlParameterPassingMechanim = "inout Array<"; SgType* baseType = array.get_base_type(); sidlParameterPassingMechanim += TransformationSupport::getTypeName(baseType); sidlParameterPassingMechanim += ",1>"; //FIXME: I don't see a way to determine the dimention of the array } // Build the substring for each parameter parameterTypesAndNames += sidlParameterPassingMechanim; parameterTypesAndNames += " "; //if(type->variantT() != V_SgTypeGlobalVoid) //{ if(type->variantT() == V_SgTypeEllipse) { parameterTypesAndNames += "Array<BabelBaseType,1> "; //FIXME: need to include a declaration for BaseType parameterTypesAndNames += "elips" + argumentCounter; //this fails to actually append the counter, but I don't think it will matter: kmk } else { SgName name = (*i)->get_name(); string nameString = name.str(); string typeName = TransformationSupport::getTypeName(type); if(typeName == "void") { if(nameString!="") { parameterTypesAndNames += "opaque "; parameterTypesAndNames += nameString; } } else { parameterTypesAndNames += typeName; parameterTypesAndNames += " "; if(nameString != "") //will be empty if the function declaration doesn't provide a name parameterTypesAndNames += nameString; } } // Add a "," to the string if there are more parameters in the list if ( argumentCounter < argumentList.size()-1 ) parameterTypesAndNames += ","; //}else printf("avoiding the void\n"); argumentCounter++; } SgType* returnType = functionType->get_return_type(); ROSE_ASSERT (returnType != NULL); string returnTypeName = "void"; if(returnType->variantT() != V_SgTypeVoid) returnTypeName = TransformationSupport::getTypeName(returnType); string sidlMemberFunctionDeclaration = " $RETURN_TYPE $FUNCTION_NAME($PARAMETERS);\n"; sidlMemberFunctionDeclaration = StringUtility::copyEdit ( sidlMemberFunctionDeclaration, "$RETURN_TYPE" , returnTypeName ); sidlMemberFunctionDeclaration = StringUtility::copyEdit ( sidlMemberFunctionDeclaration, "$FUNCTION_NAME" , sidlFunctionName ); sidlMemberFunctionDeclaration = StringUtility::copyEdit ( sidlMemberFunctionDeclaration, "$PARAMETERS" , parameterTypesAndNames ); return sidlMemberFunctionDeclaration; }
int main( int argc, char * argv[] ) { // Option to linearize the array. Rose_STL_Container<std::string> localCopy_argv = CommandlineProcessing::generateArgListFromArgcArgv(argc, argv); int newArgc; char** newArgv = NULL; vector<string> argList = localCopy_argv; if (CommandlineProcessing::isOption(argList,"-f2c:","linearize",true) == true) { isLinearlizeArray = true; } CommandlineProcessing::generateArgcArgvFromList(argList,newArgc, newArgv); // Build the AST used by ROSE SgProject* project = frontend(newArgc,newArgv); AstTests::runAllTests(project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000,"_orig"); // Traversal with Memory Pool to search for variableDeclaration variableDeclTraversal translateVariableDeclaration; traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { /* For the Fortran AST, a single variableDeclaration can be shared by multiple variables. This violated the normalization rules for C unparser. Therefore, we have to transform it. */ SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); if((variableDeclaration->get_variables()).size() != 1) { updateVariableDeclarationList(variableDeclaration); statementList.push_back(variableDeclaration); removeList.push_back(variableDeclaration); } } // reset the vector that collects all variable declaration. We need to walk through memory pool again to find types variableDeclList.clear(); traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); SgInitializedNamePtrList initializedNameList = variableDeclaration->get_variables(); for(SgInitializedNamePtrList::iterator i=initializedNameList.begin(); i!=initializedNameList.end();++i) { SgInitializedName* initiallizedName = isSgInitializedName(*i); SgType* baseType = initiallizedName->get_type(); if(baseType->variantT() == V_SgArrayType) { SgArrayType* arrayBase = isSgArrayType(baseType); // At this moment, we are still working on the Fortran-stype AST. Therefore, there is no nested types for multi-dim array. if(arrayBase->findBaseType()->variantT() == V_SgTypeString) { arrayBase->reset_base_type(translateType(arrayBase->findBaseType())); arrayBase->set_rank(arrayBase->get_rank()+1); } } else { initiallizedName->set_type(translateType(baseType)); } } } // replace the AttributeSpecificationStatement Rose_STL_Container<SgNode*> AttributeSpecificationStatement = NodeQuery::querySubTree (project,V_SgAttributeSpecificationStatement); for (Rose_STL_Container<SgNode*>::iterator i = AttributeSpecificationStatement.begin(); i != AttributeSpecificationStatement.end(); i++) { SgAttributeSpecificationStatement* attributeSpecificationStatement = isSgAttributeSpecificationStatement(*i); ROSE_ASSERT(attributeSpecificationStatement); translateAttributeSpecificationStatement(attributeSpecificationStatement); statementList.push_back(attributeSpecificationStatement); removeList.push_back(attributeSpecificationStatement); } // replace the parameter reference parameterTraversal translateParameterRef; traverseMemoryPoolVisitorPattern(translateParameterRef); for(vector<SgVarRefExp*>::iterator i=parameterRefList.begin(); i!=parameterRefList.end(); ++i) { SgVarRefExp* parameterRef = isSgVarRefExp(*i); if(parameterSymbolList.find(parameterRef->get_symbol()) != parameterSymbolList.end()) { SgExpression* newExpr = isSgExpression(deepCopy(parameterSymbolList.find(parameterRef->get_symbol())->second)); ROSE_ASSERT(newExpr); newExpr->set_parent(parameterRef->get_parent()); replaceExpression(parameterRef, newExpr, false); } } /* Parameters will be replaced by #define, all the declarations should be removed */ for(map<SgVariableSymbol*,SgExpression*>::iterator i=parameterSymbolList.begin();i!=parameterSymbolList.end();++i) { SgVariableSymbol* symbol = i->first; SgInitializedName* initializedName = symbol->get_declaration(); SgVariableDeclaration* decl = isSgVariableDeclaration(initializedName->get_parent()); statementList.push_back(decl); removeList.push_back(decl); } // Traversal with Memory Pool to search for arrayType arrayTypeTraversal translateArrayType; traverseMemoryPoolVisitorPattern(translateArrayType); for(vector<SgArrayType*>::iterator i=arrayTypeList.begin(); i!=arrayTypeList.end(); ++i) { if(isLinearlizeArray) { linearizeArrayDeclaration(*i); } else { translateArrayDeclaration(*i); } } // Traversal with Memory Pool to search for pntrArrRefExp pntrArrRefTraversal translatePntrArrRefExp; traverseMemoryPoolVisitorPattern(translatePntrArrRefExp); for(vector<SgPntrArrRefExp*>::iterator i=pntrArrRefList.begin(); i!=pntrArrRefList.end(); ++i) { if(isLinearlizeArray) { linearizeArraySubscript(*i); } else { translateArraySubscript(*i); } } Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); for (Rose_STL_Container<SgNode*>::iterator i = functionList.begin(); i != functionList.end(); i++) { if((isSgProcedureHeaderStatement(*i) != NULL) || (isSgProgramHeaderStatement(*i) != NULL)){ SgFunctionDeclaration* functionBody = isSgFunctionDeclaration(*i); bool hasReturnVal = false; if(isSgProcedureHeaderStatement(functionBody)) { hasReturnVal = isSgProcedureHeaderStatement(functionBody)->isFunction(); } fixFortranSymbolTable(functionBody->get_definition(),hasReturnVal); } } // Traversal with Memory Pool to search for equivalenceStatement equivalencelTraversal translateEquivalenceStmt; traverseMemoryPoolVisitorPattern(translateEquivalenceStmt); for(vector<SgEquivalenceStatement*>::iterator i=equivalenceList.begin(); i!=equivalenceList.end(); ++i) { SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(*i); ROSE_ASSERT(equivalenceStatement); translateEquivalenceStatement(equivalenceStatement); statementList.push_back(equivalenceStatement); removeList.push_back(equivalenceStatement); } // Simple traversal, bottom-up, to translate the rest f2cTraversal f2c; f2c.traverseInputFiles(project,postorder); // removing all the unsed statement from AST for(vector<SgStatement*>::iterator i=statementList.begin(); i!=statementList.end(); ++i) { removeStatement(*i); (*i)->set_parent(NULL); } // deepDelete the removed nodes for(vector<SgNode*>::iterator i=removeList.begin(); i!=removeList.end(); ++i) { deepDelete(*i); } /* 1. There should be no Fortran-specific AST nodes in the whole AST graph after the translation. TODO: make sure translator generating clean AST */ //generateDOT(*project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000); return backend(project); }
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); }