void FortranAnalysis::visit(SgFunctionDefinition * func_def) { SgFunctionDeclaration * func_decl = isSgFunctionDeclaration(func_def->get_declaration()); if (func_decl == NULL) return; SgInitializedNamePtrList func_args = func_decl->get_parameterList()->get_args(); SgInitializedNamePtrList::iterator arg = func_args.begin(); // for (it_args = func_args.begin(); it_args != func_args.end(); it_args++) { while (arg != func_args.end()) { SgInitializedName * func_arg = isSgInitializedName(*arg++); SgSymbol * sym = func_def->lookup_symbol(func_arg->get_name()); SgType * type = sym->get_type(); if (sym == NULL) { printf("FortranAnalysis::visit: no symbol for name %s\n", func_arg->get_name().getString().c_str()); } else if (isSgArrayType(type) != NULL) { printf("WARNING: arg %s must be a scalar\n", func_arg->get_name().str()); sym->setAttribute("dummy_attr", new AstTextAttribute("DUMMY_ARRAY_TYPE_ARG")); } else if (isSgNamedType(type)) { sym->setAttribute("dummy_attr", new AstTextAttribute("DUMMY_NAMED_TYPE_ARG")); } else { sym->setAttribute("dummy_attr", new AstTextAttribute("DUMMY_ARG")); } if (sym != NULL && isElementalArrayType(func_arg)) { sym->setAttribute("elemental_attr", new AstTextAttribute("ELEMENTAL_ARRAY")); sym->setAttribute("index_attr", new AstTextAttribute("idx")); } if (sym != NULL && hasArrayDescriptor(func_arg)) { sym->setAttribute("descriptor_attr", new AstTextAttribute("desc_"+func_arg->get_name())); sym->setAttribute("index_attr", new AstTextAttribute("idx_"+func_arg->get_name())); } } }
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 UnparseFortran_type::unparsePointerType(SgType* type, SgUnparse_Info& info, bool printAttrs) { #if 0 // printf ("Inside of UnparserFort::unparsePointerType \n"); // cur << "\n/* Inside of UnparserFort::unparsePointerType */\n"; curprint ("\n! Inside of UnparserFort::unparsePointerType \n"); #endif // DQ (1/16/2011): Note that pointers in fortran are not expressed the same as in C/C++, are are // only a part of the type which is managed more directly using attributes in the variable declaration. // Not clear that we want to do anything here in the unparser... SgPointerType* pointer_type = isSgPointerType(type); ROSE_ASSERT(pointer_type != NULL); #if 0 /* special cases: ptr to array, int (*p) [10] */ /* ptr to function, int (*p)(int) */ /* ptr to ptr to .. int (**p) (int) */ if (isSgReferenceType(pointer_type->get_base_type()) || isSgPointerType(pointer_type->get_base_type()) || isSgArrayType(pointer_type->get_base_type()) || isSgFunctionType(pointer_type->get_base_type()) || isSgMemberFunctionType(pointer_type->get_base_type()) || isSgModifierType(pointer_type->get_base_type()) ) { info.set_isPointerToSomething(); } // If not isTypeFirstPart nor isTypeSecondPart this unparse call // is not controlled from the statement level but from the type level if (info.isTypeFirstPart() == true) { unparseType(pointer_type->get_base_type(), info); // DQ (9/21/2004): Moved this conditional into this branch (to fix test2004_93.C) // DQ (9/21/2004): I think we can assert this, and if so we can simplify the logic below ROSE_ASSERT(info.isTypeSecondPart() == false); curprint("*"); } else { if (info.isTypeSecondPart() == true) { unparseType(pointer_type->get_base_type(), info); } else { SgUnparse_Info ninfo(info); ninfo.set_isTypeFirstPart(); unparseType(pointer_type, ninfo); ninfo.set_isTypeSecondPart(); unparseType(pointer_type, ninfo); } } #else if (info.supressStrippedTypeName() == false) { // DQ (1/16/2011): We only want to output the name of the stripped type once! SgType* stripType = pointer_type->stripType(); unparseType(stripType, info); info.set_supressStrippedTypeName(); } curprint(type->get_isCoArray()? ", COPOINTER": ", POINTER"); // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name). if (pointer_type->get_base_type()->containsInternalTypes() == true) { unparseType(pointer_type->get_base_type(), info, printAttrs); } #endif #if 0 // printf ("Leaving of UnparserFort::unparsePointerType \n"); // cur << "\n/* Leaving of UnparserFort::unparsePointerType */\n"; curprint ("\n! Leaving UnparserFort::unparsePointerType \n"); #endif }
void ModelBuilder::add(Model::model_t & model, SgType * sg_type) { SgModifierType * modifier_type = isSgModifierType(sg_type); if (modifier_type != NULL) { add(model, modifier_type->get_base_type()); return; } Model::type_t element = Model::build<Model::e_model_type>(); element->node->type = sg_type; SgNamedType * named_type = isSgNamedType(sg_type); SgArrayType * array_type = isSgArrayType(sg_type); SgPointerType * pointer_type = isSgPointerType(sg_type); SgReferenceType * reference_type = isSgReferenceType(sg_type); if (named_type != NULL) { SgClassType * class_type = isSgClassType(named_type); SgEnumType * enum_type = isSgEnumType(named_type); SgTypedefType * typedef_type = isSgTypedefType(named_type); SgDeclarationStatement * decl_stmt = named_type->get_declaration()->get_firstNondefiningDeclaration(); assert(decl_stmt != NULL); SgSymbol * decl_sym = decl_stmt->get_symbol_from_symbol_table(); assert(decl_sym != NULL); if (class_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_class_type; SgClassSymbol * class_sym = isSgClassSymbol(decl_sym); assert(class_sym != NULL); element->node->base_class = model.lookup_class(class_sym); if (element->node->base_class == NULL) { add(model, class_sym); element->node->base_class = model.lookup_class(class_sym); } assert(element->node->base_class != NULL); } else if (enum_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_enum_type; SgEnumSymbol * enum_sym = isSgEnumSymbol(decl_sym); assert(enum_sym != NULL); element->node->enum_symbol = enum_sym; } else if (typedef_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_typedef_type; SgTypedefSymbol * typedef_sym = isSgTypedefSymbol(decl_sym); assert(typedef_sym != NULL); element->node->typedef_symbol = typedef_sym; element->node->base_type = model.lookup_type(typedef_type->get_base_type()); if (element->node->base_type == NULL) { add(model, typedef_type->get_base_type()); element->node->base_type = model.lookup_type(typedef_type->get_base_type()); } assert(element->node->base_type != NULL); } else assert(false); } else if (array_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_array_type; element->node->base_type = model.lookup_type(array_type->get_base_type()); if (element->node->base_type == NULL) { add(model, array_type->get_base_type()); element->node->base_type = model.lookup_type(array_type->get_base_type()); } assert(element->node->base_type != NULL); } else if (pointer_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_pointer_type; element->node->base_type = model.lookup_type(pointer_type->get_base_type()); if (element->node->base_type == NULL) { add(model, pointer_type->get_base_type()); element->node->base_type = model.lookup_type(pointer_type->get_base_type()); } assert(element->node->base_type != NULL); } else if (reference_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_reference_type; element->node->base_type = model.lookup_type(reference_type->get_base_type()); if (element->node->base_type == NULL) { add(model, reference_type->get_base_type()); element->node->base_type = model.lookup_type(reference_type->get_base_type()); } assert(element->node->base_type != NULL); } else { element->node->kind = Model::node_t<Model::e_model_type>::e_native_type; } element->scope->parent.a_namespace = NULL; /// \todo model.types.push_back(element); }
void UnparseFortran_type::unparseArrayType(SgType* type, SgUnparse_Info& info, bool printDim) { // Examples: // real, dimension(10, 10) :: A1, A2 // real, dimension(:) :: B1 // character(len=*) :: s1 #if 0 curprint ("\n! Inside of UnparserFort::unparseArrayType \n"); #endif SgArrayType* array_type = isSgArrayType(type); ROSE_ASSERT(array_type != NULL); // I think that supressStrippedTypeName() and SkipBaseType() are redundant... if (info.supressStrippedTypeName() == false) { // DQ (1/16/2011): We only want to output the name of the stripped type once! SgType* stripType = array_type->stripType(); unparseType(stripType, info); info.set_supressStrippedTypeName(); } // DQ (8/5/2010): It is an error to treat an array of char as a string (see test2010_16.f90). #if 0 // dimension information SgExprListExp* dim = array_type->get_dim_info(); // if (isCharType(array_type->get_base_type())) // if (false && isCharType(array_type->get_base_type())) if (isCharType(array_type->get_base_type())) { // a character type: must be treated specially ROSE_ASSERT(array_type->get_rank() == 1); curprint("(len="); SgExpressionPtrList::iterator it = dim->get_expressions().begin(); if (it != dim->get_expressions().end()) { SgExpression* expr = *it; if (expr->variantT() == V_SgSubscriptExpression) { // this is a subscript expression but all we want to unparse is the length // of the string, which should be the upper bound of the subscript expression SgSubscriptExpression* sub_expr = isSgSubscriptExpression(expr); ROSE_ASSERT(sub_expr != NULL); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); unp->u_fortran_locatedNode->unparseExpression(sub_expr->get_upperBound(), info); } else { // unparse the entire expression ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); unp->u_fortran_locatedNode->unparseExpression(*it, info); } } else { curprint("*"); } curprint(")"); } else { // a non-character type // explicit-shape (explicit rank and bounds/extents) // assumed-shape (explicit rank; unspecified bounds/extents) // deferred-shape (explicit rank; unspecified bounds/extents) // assumed-size (explicit ranks, explicit bounds/extents except last dim) ROSE_ASSERT(array_type->get_rank() >= 1); curprint(", DIMENSION"); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); // unp->u_fortran_locatedNode->unparseExprList(dim, info); // adds parens // unp->u_fortran_locatedNode->UnparseLanguageIndependentConstructs::unparseExprList(dim, info); // adds parens // curprint("("); // curprint( StringUtility::numberToString(array_type->get_rank()) ); // curprint(")"); // unp->u_fortran_locatedNode->unparseExpression(array_type->get_dim_info(),info); unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true); } #else if (printDim) { ROSE_ASSERT(array_type->get_rank() >= 1); curprint(array_type->get_isCoArray()? ", CODIMENSION": ", DIMENSION"); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); if (array_type->get_isCoArray()) { // print codimension info curprint("["); unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* do not output parens */ false); curprint("]"); } else // print dimension info unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true); } // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name). if (array_type->get_base_type()->containsInternalTypes() == true) { unparseType(array_type->get_base_type(), info, printDim); } #endif #if 0 curprint ("\n! Leaving UnparserFort::unparseArrayType \n"); #endif }
// DQ (4/7/2004): Added to support more general lookup of data in the AST (vector of variants) void* querySolverGrammarElementFromVariantVector ( SgNode * astNode, VariantVector targetVariantVector, NodeQuerySynthesizedAttributeType* returnNodeList ) { // This function extracts type nodes that would not be traversed so that they can // accumulated to a list. The specific nodes collected into the list is controlled // by targetVariantVector. ROSE_ASSERT (astNode != NULL); #if 0 printf ("Inside of void* querySolverGrammarElementFromVariantVector() astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif Rose_STL_Container<SgNode*> nodesToVisitTraverseOnlyOnce; pushNewNode (returnNodeList,targetVariantVector,astNode); vector<SgNode*> succContainer = astNode->get_traversalSuccessorContainer(); vector<pair<SgNode*,string> > allNodesInSubtree = astNode->returnDataMemberPointers(); #if 0 printf ("succContainer.size() = %zu \n",succContainer.size()); printf ("allNodesInSubtree.size() = %zu \n",allNodesInSubtree.size()); #endif if ( succContainer.size() != allNodesInSubtree.size() ) { for (vector<pair<SgNode*,string> >::iterator iItr = allNodesInSubtree.begin(); iItr!= allNodesInSubtree.end(); ++iItr ) { #if 0 if ( iItr->first != NULL ) { // printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); printf ("iItr->first = %p \n",iItr->first); printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); } #endif // DQ (7/27/2014): Check if this is always non-NULL. // ROSE_ASSERT(iItr->first != NULL); #if 0 if (iItr->first != NULL) { // printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d class_name = %s \n",iItr->first->variantT(),iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first = %p \n",iItr->first); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->class_name = %s \n",iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d \n",(int)iItr->first->variantT()); } else { printf ("In querySolverGrammarElementFromVariantVector(): iItr->first == NULL \n"); } #endif SgType* type = isSgType(iItr->first); if ( type != NULL ) { // DQ (1/13/2011): If we have not already seen this entry then we have to chase down possible nested types. // if (std::find(succContainer.begin(),succContainer.end(),iItr->first) == succContainer.end() ) if (std::find(succContainer.begin(),succContainer.end(),type) == succContainer.end() ) { // DQ (1/30/2010): Push the current type onto the list first, then any internal types... pushNewNode (returnNodeList,targetVariantVector,type); // Are there any other places where nested types can be found...? // if ( isSgPointerType(iItr->first) != NULL || isSgArrayType(iItr->first) != NULL || isSgReferenceType(iItr->first) != NULL || isSgTypedefType(iItr->first) != NULL || isSgFunctionType(iItr->first) != NULL || isSgModifierType(iItr->first) != NULL) // if (type->containsInternalTypes() == true) if (type->containsInternalTypes() == true) { #if 0 printf ("If we have not already seen this entry then we have to chase down possible nested types. \n"); // ROSE_ASSERT(false); #endif Rose_STL_Container<SgType*> typeVector = type->getInternalTypes(); #if 0 printf ("----- typeVector.size() = %zu \n",typeVector.size()); #endif Rose_STL_Container<SgType*>::iterator i = typeVector.begin(); while(i != typeVector.end()) { #if 0 printf ("----- internal type = %s \n",(*i)->class_name().c_str()); #endif // DQ (1/16/2011): This causes a test in tests/roseTests/programAnalysisTests/variableLivenessTests // to fail with error "Error :: Number of nodes = 37 should be : 36" // Add this type to the return list of types. pushNewNode (returnNodeList,targetVariantVector,*i); i++; } } // DQ (1/30/2010): Move this code to the top of the basic block. // pushNewNode (returnNodeList,targetVariantVector,iItr->first); // pushNewNode (returnNodeList,targetVariantVector,type); } } } } #if 0 // This code cannot be put here. Since the same SgVarRefExp will also be found during variable substitution phase. // We don't want to replace the original SgVarRefExp!! // Liao 1/19/2011. query the dim_info of SgArrayType associated with SgPntrArrRefExp // e.g. assuming a subtree has a reference to an array, then the variables used to declare the array dimensions should also be treated as referenced/used by the subtree // even though the reference is indirect. // AST should look like: // SgPntrArrRefExp -> SgVarRefExp (lhs) -> SgVariableSymbol(symbol) -> SgInitializedName -> SgArrayType (typeptr) -> SgExprListExp (dim_info) // AST outlining needs to find indirect use of a variable to work properly if (std::find(targetVariantVector.begin(), targetVariantVector.end(), V_SgVarRefExp) != targetVariantVector.end()) // Only do this if SgVarRefExp is of interest { if (SgPntrArrRefExp * arr_exp = isSgPntrArrRefExp(astNode)) { printf("Debug: queryVariant.C Found SgPntrArrRefExp :%p\n", arr_exp); Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp); // find the array reference from the lhs operand, which could be a complex arithmetic expression SgVarRefExp* array_ref = NULL; for (Rose_STL_Container<SgNode*>::iterator iter = refList.begin(); iter !=refList.end(); iter ++) { SgVarRefExp* cur_ref = isSgVarRefExp(*iter); ROSE_ASSERT (cur_ref != NULL); SgVariableSymbol * sym = cur_ref->get_symbol(); ROSE_ASSERT (sym != NULL); SgInitializedName * i_name = sym->get_declaration(); ROSE_ASSERT (i_name != NULL); SgArrayType * a_type = isSgArrayType(i_name->get_typeptr()); if (a_type) { Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp); for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++) { SgVarRefExp* dim_ref = isSgVarRefExp(*iter2); printf("Debug: queryVariant.C Found indirect SgVarRefExp as part of array dimension declaration:%s\n", dim_ref->get_symbol()->get_name().str()); pushNewNode (returnNodeList, targetVariantVector, *iter2); } } } } // end if SgPntrArrRefExp } // end if find() #endif return NULL; } /* End function querySolverUnionFields() */
//! 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; }
/* * Add calls to register and unregister expressions/arrays with the memory * management wrapper. */ bool RegisterPointers::addRegUnregCalls() { string msg; if(definedInSystemHeader) { msg = "\t\t\tVariable " + NAME(varSymbol) + " is in system headers"; WARNING(TOOL, msg); return false; } if(compilerGenerated) { msg = "\t\t\tVariable " + NAME(varSymbol) + " is compiler-generated"; WARNING(TOOL, msg); return false; } if(addrUsedInIO) { msg = "\t\t\tVariable " + NAME(varSymbol) + " has its address taken in " + "a function known to not require registering/unregistering"; WARNING(TOOL, msg); return false; } //Add register/unregister calls SgStatement* prevStmt = NULL; SgExprStatement* funcCall = NULL; SgType* type = NULL; SgExpression* expr = NULL; if(isGlobal) { type = varName->get_type(); SgName name = varName->get_name(); int numVals = 1; if(isSgPointerType(type)) return false; //If its a pointer, it points to a static array, dynamic array, or scalar //which has its address taken (all of which have already been registered) SgFunctionDeclaration* main = findMain(getScope(varName)); ROSE_ASSERT(main); expr = buildVarRefExp(name, varName->get_scope()); if(isSgArrayType(type)) numVals = getArrayElementCount(isSgArrayType(type)); else expr = buildAddressOfOp(expr); funcCall = MMCallBuilder::buildRegisterPointerCall(expr, buildUnsignedIntVal(numVals), main->get_definition()); insertStatement(getFirstStatement(main->get_definition()), funcCall);//, false, true); funcCall = MMCallBuilder::buildUnregisterPointerCall(expr, main->get_definition()); instrumentEndOfFunction(main, funcCall); } else if(expression) //Address-of expressions { prevStmt = getEnclosingStatement(expression); funcCall = MMCallBuilder::buildRegisterPointerCall(expression, buildUnsignedIntVal(1), getScope(expression)); insertStatement(prevStmt, funcCall); funcCall = MMCallBuilder::buildUnregisterPointerCall(expression, getScope(expression)); instrumentEndOfFunction(getEnclosingFunctionDeclaration(prevStmt), funcCall); } else //Array types { SgVarRefExp* varRef = buildVarRefExp(varName, getScope(varName)); int numVals = getArrayElementCount(isSgArrayType(varName->get_type())); funcCall = MMCallBuilder::buildRegisterPointerCall(varRef, buildUnsignedIntVal(numVals), varName->get_scope()); insertStatement(varName->get_declaration(), funcCall, false, true); varRef = buildVarRefExp(varName, getScope(varName)); funcCall = MMCallBuilder::buildUnregisterPointerCall(varRef, varName->get_scope()); instrumentEndOfFunction(getEnclosingFunctionDeclaration(varName), funcCall); } return true; }
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); }
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 VerifyOriginalExpressionTreesSetToNull::visit ( SgNode* node ) { // This traversal is used to verify that all of the original expression trees in the AST have // been either deleted (optional) or used to replace the constant folded values (the default // for the ROSE AST so that we can preserve the greatest amount of source-to-source detail). // Note that it can detect problems that are due to orphaned expressions in the AST. // An example is test2011_138.C where the multidimensional array indexing causes and orphaned // expression to be created and it has a original expression tree. Since the orphaned expression // can't be reached we can eliminate the original expression tree. The bug in ROSE is that there // is an orphaned expression tree not that there is a remaining original expression tree. // We need a mechanism to detect nodes that exist in the AST and are not pointed to by any other // IR node (and then we have to decide if parent pointers count). ROSE_ASSERT(node != NULL); // printf ("In VerifyOriginalExpressionTreesSetToNull::visit(): node = %s \n",node->class_name().c_str()); SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("Error: there is a valid originalExpressionTree = %p = %s on node = %p = %s \n",originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str()); #endif } #if 0 // Liao debugging 11/13/2012 ROSE_ASSERT(originalExpressionTree == NULL); #endif // Allow us to ignore the cases of originalExpressionTrees hidden in array types. // I want to narrow down the failing tests codes to eliminate this case which is handled separately. if (originalExpressionTree != NULL) { #if 0 SgNode* parent = exp; // Note that test2011_121.C fails to be either a SgArrayType or a SgVariableDefinition (failing in some part of "complex" header file). // test2005_203.C demonstrates the use of constant folding in bitfield specifications. // while (parent != NULL && isSgArrayType(parent) == NULL) while (parent != NULL && isSgArrayType(parent) == NULL && isSgVariableDefinition(parent) == NULL) { parent = parent->get_parent(); } if (isSgArrayType(parent) == NULL) { printf ("So what is the parent: parent = %p = %s \n",parent, (parent != NULL) ? parent->class_name().c_str() : "NULL"); } ROSE_ASSERT(isSgArrayType(parent) != NULL || isSgVariableDefinition(parent) != NULL); #else #ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION printf ("In VerifyOriginalExpressionTreesSetToNull(): originalExpressionTree = %p = %s on node = %p = %s Ingoring originalExpressionTree != NULL \n", originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str()); #endif #endif } } }
/** * 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; }
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 } } } }
/*! * \brief Creates a new outlined-function parameter for a given * variable. The requirement is to preserve data read/write semantics. * * For C/C++: we use pointer dereferencing to implement pass-by-reference * In a recent implementation, side effect analysis is used to find out * variables which are not modified so pointer types are not used. * * * Given a variable (i.e., its type and name) whose references are to * be outlined, create a suitable outlined-function parameter. * For C/C++, the parameter is created as a pointer, to support parameter passing of * aggregate types in C programs. * Moreover, the type is made 'void' if the base type is not a primitive type. * * An original type may need adjustments before we can make a pointer type from it. * For example: * a)Array types from a function parameter: its first dimension is auto converted to a pointer type * * b) Pointer to a C++ reference type is illegal, we create a pointer to its * base type in this case. It also match the semantics for addressof(refType) * * * The implementation follows two steps: * step 1: adjust a variable's base type * step 2: decide on its function parameter type * Liao, 8/14/2009 */ static OutlinedFuncParam_t createParam (const SgInitializedName* i_name, bool readOnly=false) { ROSE_ASSERT (i_name); SgType* init_type = i_name->get_type(); ROSE_ASSERT (init_type); // Stores the real parameter type to be used in new_param_type string init_name = i_name->get_name ().str (); SgType* param_base_type; //has to be not scalar if(isSgArrayType (init_type) ){ SgType* base_type = init_type->findBaseType(); param_base_type = buildPointerType(base_type); } else if (isSgPointerType (init_type)) { //Didem, this used to be 2 but I changed into 0. Didn't make any sense init_name = init_name.substr(0); //Didem: I have changed the types into 1D pointer type SgType* base_type = init_type->findBaseType(); param_base_type = buildPointerType(base_type); //param_base_type = init_type; } else{ param_base_type = init_type; } // The parameter name reflects the type: the same name means the same type, // p__ means a pointer type string new_param_name = init_name; SgType* new_param_type = NULL; // For classic behavior, read only variables are passed by values for C/C++ // They share the same name and type if (Outliner::enable_classic) { // read only parameter: pass-by-value, the same type and name // shared parameters : already pointer type //if (readOnly) { new_param_type = param_base_type; } /* else { new_param_name= "d__" + new_param_name; new_param_type = SgPointerType::createType (param_base_type); }*/ } else // very conservative one, assume the worst side effects (all are written) { new_param_name= new_param_name; } // So use base type directly // C/C++ parameters will use their new param type to implement pass-by-reference return OutlinedFuncParam_t (new_param_name, new_param_type); }
bool Type::isArray() const { return isSgArrayType(t_) != 0; }
std::string getSgInitializedName(SgInitializedName* initName) { std::string exprStr; SgSymbol* initNameSym = initName->search_for_symbol_from_symbol_table(); std::string varInit = initializeVariable(initName); std::string retString; if (initName->get_initptr() != NULL) { SgInitializer* nameInitializer = initName->get_initializer(); VariantT var = nameInitializer->variantT(); switch (var) { case V_SgAggregateInitializer: { SgAggregateInitializer* aggInit = isSgAggregateInitializer(nameInitializer); if (!isSgArrayType(aggInit->get_type())) { std::cout << "currently only arrays use aggregate initializers, you are using " << aggInit->class_name() << std::endl; ROSE_ASSERT(false); } SgExprListExp* members = aggInit->get_initializers(); SgExpressionPtrList member_expressions = members->get_expressions(); std::string symName = SymbolToZ3[initNameSym]; ROSE_ASSERT(SymbolToInstances[initNameSym] == 0); int arrmem = 0; std::stringstream exprStream; for (SgExpressionPtrList::iterator i = member_expressions.begin(); i != member_expressions.end(); i++) { exprStream << "\n(assert (= (select " << symName << "_0 " << arrmem << ") " << getSgExpressionString((isSgAssignInitializer((*i))->get_operand())) << ")"; arrmem = arrmem+1; } retString = varInit + "\n" + exprStream.str(); #ifdef ARRAY_TEST std::cout << "retString: " << retString << std::endl; #endif break; } case V_SgCompoundInitializer: { std::cout << "SgCompoundInitializer not yet supported" << std::endl; ROSE_ASSERT(false); break; } case V_SgConstructorInitializer: { std::cout << "SgConstructorInitializer is not yet supported" << std::endl; ROSE_ASSERT(false); break; } case V_SgDesignatedInitializer: { std::cout << "SgDesignatedInitializer is not yet supported" << std::endl; ROSE_ASSERT(false); break; } case V_SgAssignInitializer: { SgAssignInitializer* assignInit = isSgAssignInitializer(nameInitializer); std::string symName = SymbolToZ3[initNameSym]; ROSE_ASSERT(SymbolToInstances[initNameSym] == 0); exprStr = "(assert (= " + symName + "_0 " + getSgExpressionString(assignInit->get_operand()) + "))"; retString = varInit + "\n" + exprStr; break; } default: { std::cout << "unknown initializer of type: " << nameInitializer->class_name() << std::endl; ROSE_ASSERT(false); break; } } } else { retString = varInit; } return retString; }
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 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(); }