// given a function call, sets argParamMap to map all simple arguments to this function to their 
// corresponding parameters
void FunctionState::setArgParamMap(SgFunctionCallExp* call, map<varID, varID>& argParamMap)
{
        Function func(call);
        
        SgExpressionPtrList args = call->get_args()->get_expressions();
        //SgInitializedNamePtrList params = funcArgToParamByRef(call);
        SgInitializedNamePtrList params = func.get_params();
        ROSE_ASSERT(args.size() == params.size());
        
        //cout << "setArgParamMap() #args="<<args.size()<<" #params="<<params.size()<<"\n";
        // the state of the callee's variables at the call site
        SgExpressionPtrList::iterator itA;
        SgInitializedNamePtrList::iterator itP;
        for(itA = args.begin(), itP = params.begin(); 
            itA!=args.end() && itP!=params.end(); 
            itA++, itP++)
        {
                //cout << "    itA="<<(*itA)->unparseToString()<<" itP="<<(*itP)->unparseToString()<<" isValid="<<varID::isValidVarExp(*itA)<<"\n";
                /*if(varID::isValidVarExp(*itA))
                {
                        varID arg(*itA);
                        varID param(*itP);
                        argParamMap[arg] = param;
                }*/
                varID arg = SgExpr2Var(*itA);
                varID param(*itP);
                argParamMap[arg] = param;
        }
}
Exemple #2
0
void Fortran_to_C::linearizeArrayDeclaration(SgArrayType* originalArrayType)
{
  // Get dim_info
  SgExprListExp* dimInfo = originalArrayType->get_dim_info();
  // Get dim list
  SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions();

  SgExpression* newDimExpr; 
  Rose_STL_Container<SgExpression*>::iterator j =  dimExpressionPtrList.begin();
  while(j != dimExpressionPtrList.end())
  {
    SgExpression* indexExpression = getFortranDimensionSize(*j);

    /*
      Total array size is equal to the multiplication of all individual dimension size.
    */
    if(j != dimExpressionPtrList.begin()){
        newDimExpr = buildMultiplyOp(newDimExpr, indexExpression);
    }
    else
    /*
      If it's first dimension, array size is just its first dimension size.
    */
    {
      newDimExpr = indexExpression;
    }
    ++j;
  }
  // calling set_index won't replace the default index expression.  I have to delete the default manually.
  removeList.push_back(originalArrayType->get_index());
  originalArrayType->set_index(newDimExpr);
  newDimExpr->set_parent(originalArrayType);
  originalArrayType->set_rank(1); 
}
int BasicProgmemTransform::getBuffersizeNeededForFunction(SgFunctionDeclaration *func) {
	int maxSize = 0;
	Rose_STL_Container<SgNode *> funcCalls = NodeQuery::querySubTree(func, V_SgFunctionCallExp);
	for(auto &funcCall: funcCalls) {
		SgFunctionCallExp *fcall = isSgFunctionCallExp(funcCall);
		Function callee(fcall);
//		printf("function called: %s\n", callee.get_name().str());
		if(isArduinoProgmemSafeFunction(callee)) {
			continue;
		}
		param_pos_list ignoredPositions = getPositionsToIgnore(callee.get_name().getString());
		SgExpressionPtrList params = fcall->get_args()->get_expressions();
		int size = 0;
		for(int pos = 0; pos < params.size(); pos++) {
			if(ignoredPositions.find(pos) != ignoredPositions.end()) {
				continue;
			}
			SgVarRefExp* var = isSgVarRefExp(params[pos]);
			if(var) {
				SgInitializedName *initName = var->get_symbol()->get_declaration();
				if(isVarDeclToRemove(initName)) {
					SgExpression *rhs = getRHSOfVarDecl(initName);
					if(rhs && isSgStringVal(rhs)) {
						size += isSgStringVal(rhs)->get_value().size() + 1;
					}
				}
			}
		}
		if(size > maxSize) {
			maxSize = size;
		}
	}
	return maxSize;
}
void BasicProgmemTransform::transformFunction(SgFunctionDeclaration *func) {
	setupCharBufferForFunction(func);
	Rose_STL_Container<SgNode *> funcCalls = NodeQuery::querySubTree(func, V_SgFunctionCallExp);

	for(auto &funcCall: funcCalls) {
		int startPos = 0;
		SgFunctionCallExp *fcall = isSgFunctionCallExp(funcCall);
		Function callee(fcall);
		std::string orig = callee.get_name().getString();
		std::string replacement = getReplacementName(orig);
		bool arduinoP = isArduinoProgmemSafeFunction(callee);
		SgExpressionPtrList params = fcall->get_args()->get_expressions();
		param_pos_list progmemPositions = getPositionsToIgnore(orig);
		//TODO: figure out how to wrap with macro
//		for(auto &expr: params) {
		for(int index = 0; index < params.size(); index++){
			SgExpression *expr = params[index];
			SgVarRefExp* var = isSgVarRefExp(expr);
			if(var == NULL) { continue;}
			if(isVarDeclToRemove(var)) {
				if(arduinoP) {
					castProgmemParams(var);
				} else if(progmemPositions.find(index) == progmemPositions.end()) {
					loadProgmemStringsIntoBuffer(fcall, var, startPos);
				}
			}
		}
		if(replacement != "") {
			loadReplacewithProgmemFunction(fcall, replacement);
		}
	}
}
/*! 
  * \author Markus Schordan
  * \date 2014.
 */
void SPRAY::LVTransferFunctions::transferFunctionCall(Label lab,  SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element0) {
  LVLattice* element1=dynamic_cast<LVLattice*>(&element0);
  ROSE_ASSERT(element1);
  LVLattice& element=*element1;

  // uses and defs in argument-expressions
  for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) {
    transferExpression(lab,*i,element);
  }
}
/*! 
  * \author Markus Schordan
  * \date 2014.
 */
void SPRAY::IntervalTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element) {
  // uses and defs in argument-expressions
  int paramNr=0;
  IntervalPropertyState* ips=dynamic_cast<IntervalPropertyState*>(&element);
  for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) {
    // TODO: add one variable $paramX for each parameter to the state and bind it to the value of the argument
    VariableId paramId=getParameterVariableId(paramNr);
    ips->addVariable(paramId);
    ips->setVariable(paramId,evalExpression(lab,*i,element));
  }
}
/*! 
  * \author Markus Schordan
  * \date 2013.
 */
void RDTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element0) {
  RDLattice& element=dynamic_cast<RDLattice&>(element0);

  // uses and defs in argument-expressions
  int paramNr=0;
  for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) {
    VariableId paramId=getParameterVariableId(paramNr);
    transferExpression(lab,*i,element);
    // insert parameter variable
    element.insertPair(lab,paramId);
    paramNr++;
  }
}
// given a function call, sets argParamMap to map all the parameters of this function to their 
// corresponding simple arguments, if those arguments are passed by reference
void FunctionState::setParamArgByRefMap(SgFunctionCallExp* call, map<varID, varID>& paramArgByRefMap)
{
        Function func(call);

        SgExpressionPtrList args = call->get_args()->get_expressions(); 
        SgInitializedNamePtrList params = func.get_params();
        
        SgExpressionPtrList::iterator itArgs;
        SgInitializedNamePtrList::iterator itParams;
        //cout << "            #params="<<params.size()<<" #args="<<args.size()<<"\n";
        for(itParams = params.begin(), itArgs = args.begin(); 
            itParams!=params.end() && itArgs!=args.end(); 
            itParams++, itArgs++)
        {
                /*SgType* typeParam = (*itParams)->get_type();
                SgType* typeArg = cfgUtils::unwrapCasts((*itArgs))->get_type();*/
                        
                /*printf("FunctionState::setParamArgByRefMap() *itArgs=<%s | %s> isValidVar=%d\n", (*itArgs)->unparseToString().c_str(), (*itArgs)->class_name().c_str(), varID::isValidVarExp(*itArgs));
                printf("                                     typeArg=<%s | %s>\n", typeArg->unparseToString().c_str(), typeArg->class_name().c_str());
                printf("                                     itParams=<%s | %s>\n", (*itParams)->unparseToString().c_str(), (*itParams)->class_name().c_str());
                printf("                                     typeParam=<%s | %s> isReference=%d\n", typeParam->unparseToString().c_str(), typeParam->class_name().c_str(), isSgReferenceType(typeParam));*/
                
                /*      // if the argument is a named variable AND
                if(varID::isValidVarExp(*itArgs) && 
                         // if the argument has an array type, it's contents will be passed by reference OR 
                        ((isSgArrayType(typeArg) || isSgPointerType(typeArg)) ||
                         // if the argument is a regular variable, by the parameter has a reference type, 
                         // or the variable is being passed via a pointer, the variable must be passed by reference
                         isSgReferenceType(typeParam)))
                {
                        varID argVar(*itArgs);
                        varID paramVar(*itParams);
                        
                        // add this mapping
                        paramArgByRefMap[paramVar] = argVar;
                }*/
                varID argVar = SgExpr2Var(*itArgs);
                varID paramVar(*itParams);
                
                // add this mapping
                paramArgByRefMap[paramVar] = argVar;
                
                /*
                // if the argument is a non-array variable being passed via a pointer
                else if(isSgAddressOfOp(*itArgs) && SgPointerType(typeArg) && 
                             SgPointerType(typeParam)*/
        }
}
Exemple #9
0
void Fortran_to_C::translateArrayDeclaration(SgArrayType* originalArrayType)
{
  // Get dim_info
  SgExprListExp* dimInfo = originalArrayType->get_dim_info();
  // Get dim list
  SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions();
  // Get array base_type
  SgType* baseType = originalArrayType->get_base_type();

  Rose_STL_Container<SgExpression*>::iterator j =  dimExpressionPtrList.begin();
  SgExpression* indexExpression = getFortranDimensionSize(*j);
  //std::cout << "array rank:" << originalArrayType->get_rank() << std::endl;
  if(originalArrayType->get_rank() == 1)
  {
    originalArrayType->set_base_type(baseType);
    originalArrayType->set_index(indexExpression);
    indexExpression->set_parent(originalArrayType);
    constantFolding(indexExpression);
  }
  else
  {
    SgArrayType* newType = buildArrayType(baseType,indexExpression);
    baseType->set_parent(newType);
    j = j + 1;
    for(; j< (dimExpressionPtrList.end()-1); ++j)
    {
      indexExpression = getFortranDimensionSize(*j);
      baseType = newType;
      newType = buildArrayType(baseType,indexExpression);
      baseType->set_parent(newType);
    }
    j = dimExpressionPtrList.end()-1;
    indexExpression = getFortranDimensionSize(*j);
    originalArrayType->set_base_type(newType);
    originalArrayType->set_index(indexExpression);
    indexExpression->set_parent(originalArrayType);
  }
}
bool expressionTreeEqualStar(const SgExpressionPtrList& as,
                             const SgExpressionPtrList& bs) {
  SgExpressionPtrList::const_iterator i, j;
  for (i = as.begin(), j = bs.begin(); i != as.end() && j != bs.end(); ++i, ++j)
    if (!expressionTreeEqual(*i, *j))
      return false;
  if (i != as.end() || j != bs.end())
    return false; // Mismatched lengths
  return true;
}
Exemple #11
0
// Main inliner code.  Accepts a function call as a parameter, and inlines
// only that single function call.  Returns true if it succeeded, and false
// otherwise.  The function call must be to a named function, static member
// function, or non-virtual non-static member function, and the function
// must be known (not through a function pointer or member function
// pointer).  Also, the body of the function must already be visible.
// Recursive procedures are handled properly (when allowRecursion is set), by
// inlining one copy of the procedure into itself.  Any other restrictions on
// what can be inlined are bugs in the inliner code.
bool
doInline(SgFunctionCallExp* funcall, bool allowRecursion)
   {
#if 0
  // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag.
     ROSE_ASSERT(funcall != NULL);
     ROSE_ASSERT(funcall->get_parent() != NULL);
     SgGlobal* globalScope = TransformationSupport::getGlobalScope(funcall);
     ROSE_ASSERT(globalScope != NULL);
  // checkTransformedFlagsVisitor(funcall->get_parent());
     checkTransformedFlagsVisitor(globalScope);
#endif

     SgExpression* funname = funcall->get_function();
     SgExpression* funname2 = isSgFunctionRefExp(funname);
     SgDotExp* dotexp = isSgDotExp(funname);
     SgArrowExp* arrowexp = isSgArrowExp(funname);
     SgExpression* thisptr = 0;
     if (dotexp || arrowexp)
        {
          funname2 = isSgBinaryOp(funname)->get_rhs_operand();
          if (dotexp) {
            SgExpression* lhs = dotexp->get_lhs_operand();

            // FIXME -- patch this into p_lvalue
            bool is_lvalue = lhs->get_lvalue();
            if (isSgInitializer(lhs)) is_lvalue = false;

            if (!is_lvalue) {
              SgAssignInitializer* ai = SageInterface::splitExpression(lhs);
              ROSE_ASSERT (isSgInitializer(ai->get_operand()));
#if 1
              printf ("ai = %p ai->isTransformation() = %s \n",ai,ai->isTransformation() ? "true" : "false");
#endif
              SgInitializedName* in = isSgInitializedName(ai->get_parent());
              ROSE_ASSERT (in);
              removeRedundantCopyInConstruction(in);
              lhs = dotexp->get_lhs_operand(); // Should be a var ref now
            }
            thisptr = new SgAddressOfOp(SgNULL_FILE, lhs);
          } else if (arrowexp) {
            thisptr = arrowexp->get_lhs_operand();
          } else {
            assert (false);
          }
        }

     if (!funname2)
        {
       // std::cout << "Inline failed: not a call to a named function" << std::endl;
          return false; // Probably a call through a fun ptr
        }

     SgFunctionSymbol* funsym = 0;
     if (isSgFunctionRefExp(funname2))
          funsym = isSgFunctionRefExp(funname2)->get_symbol();
       else
          if (isSgMemberFunctionRefExp(funname2))
               funsym = isSgMemberFunctionRefExp(funname2)->get_symbol();
            else
               assert (false);

     assert (funsym);
     if (isSgMemberFunctionSymbol(funsym) &&
         isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual())
        {
       // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl;
          return false;
        }

     SgFunctionDeclaration* fundecl = funsym->get_declaration();
     fundecl = fundecl ? isSgFunctionDeclaration(fundecl->get_definingDeclaration()) : NULL;

     SgFunctionDefinition* fundef = fundecl ? fundecl->get_definition() : NULL;
     if (!fundef)
        {
       // std::cout << "Inline failed: no definition is visible" << std::endl;
          return false; // No definition of the function is visible
        }
     if (!allowRecursion)
        {
          SgNode* my_fundef = funcall;
          while (my_fundef && !isSgFunctionDefinition(my_fundef))
             {
            // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str());
               my_fundef = my_fundef->get_parent();
               ROSE_ASSERT(my_fundef != NULL);
            // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str());
             }
       // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str());
          assert (isSgFunctionDefinition(my_fundef));
          if (isSgFunctionDefinition(my_fundef) == fundef)
             {
               std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl;
               return false;
             }
        }

     SgVariableDeclaration* thisdecl = 0;
     SgName thisname("this__");
     thisname << ++gensym_counter;
     SgInitializedName* thisinitname = 0;
     if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic())
        {
          assert (thisptr != NULL);
          SgType* thisptrtype = thisptr->get_type();
          const SgSpecialFunctionModifier& specialMod = 
            funsym->get_declaration()->get_specialFunctionModifier();
          if (specialMod.isConstructor()) {
            SgFunctionType* ft = funsym->get_declaration()->get_type();
            ROSE_ASSERT (ft);
            SgMemberFunctionType* mft = isSgMemberFunctionType(ft);
            ROSE_ASSERT (mft);
            SgType* ct = mft->get_class_type();
            thisptrtype = new SgPointerType(ct);
          }
          SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier();
       // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME
          thisptrtype = new SgModifierType(thisptrtype);
          isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv;
       // }
       // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl;
          SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr);
          assignInitializer->set_endOfConstruct(SgNULL_FILE);
#if 1
          printf ("before new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false");
#endif
          thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer);
#if 1
          printf ("(after new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false");
#endif
          thisdecl->set_endOfConstruct(SgNULL_FILE);
          thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE);
          thisdecl->set_definingDeclaration(thisdecl);

          thisinitname = (thisdecl->get_variables()).back();
          //thisinitname = lastElementOfContainer(thisdecl->get_variables());
          // thisinitname->set_endOfConstruct(SgNULL_FILE);
          assignInitializer->set_parent(thisinitname);
          markAsTransformation(assignInitializer);

       // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl);

       // DQ (6/23/2006): New test
          ROSE_ASSERT(assignInitializer->get_parent() != NULL);
        }

     // Get the list of actual argument expressions from the function call, which we'll later use to initialize new local
     // variables in the inlined code.  We need to detach the actual arguments from the AST here since we'll be reattaching
     // them below (otherwise we would violate the invariant that the AST is a tree).
     SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall);
     SgExpressionPtrList funargs = funcall->get_args()->get_expressions();
     funcall->get_args()->get_expressions().clear();
     BOOST_FOREACH (SgExpression *actual, funargs)
         actual->set_parent(NULL);

     // Make a copy of the to-be-inlined function so we're not modifying and (re)inserting the original.
     SgBasicBlock* funbody_raw = fundef->get_body();
     SgInitializedNamePtrList& params = fundecl->get_args();
     std::vector<SgInitializedName*> inits;
     SgTreeCopy tc;
     SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc));
     ROSE_ASSERT (function_copy);
     SgBasicBlock* funbody_copy = function_copy->get_body();

     renameLabels(funbody_copy, targetFunction);
     ASSERT_require(funbody_raw->get_symbol_table()->size() == funbody_copy->get_symbol_table()->size());

     // We don't need to keep the copied SgFunctionDefinition now that the labels in it have been moved to the target function
     // (having it in the memory pool confuses the AST tests), but we must not delete the formal argument list or the body
     // because we need them below.
     if (function_copy->get_declaration()) {
         ASSERT_require(function_copy->get_declaration()->get_parent() == function_copy);
         function_copy->get_declaration()->set_parent(NULL);
         function_copy->set_declaration(NULL);
     }
     if (function_copy->get_body()) {
         ASSERT_require(function_copy->get_body()->get_parent() == function_copy);
         function_copy->get_body()->set_parent(NULL);
         function_copy->set_body(NULL);
     }
     delete function_copy;
     function_copy = NULL;
#if 0
     SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE);
     SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin);
     pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE);
     pragmaBegin->set_parent(pragmaBeginDecl);
     pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl);
     funbody_copy->prepend_statement(pragmaBeginDecl);
     pragmaBeginDecl->set_parent(funbody_copy);
#endif

     // In the to-be-inserted function body, create new local variables with distinct non-conflicting names, one per formal
     // argument and having the same type as the formal argument. Initialize those new local variables with the actual
     // arguments.  Also, build a paramMap that maps each formal argument (SgInitializedName) to its corresponding new local
     // variable (SgVariableSymbol).
     ReplaceParameterUseVisitor::paramMapType paramMap;
     SgInitializedNamePtrList::iterator formalIter = params.begin();
     SgExpressionPtrList::iterator actualIter = funargs.begin();
     for (size_t argNumber=0;
          formalIter != params.end() && actualIter != funargs.end();
          ++argNumber, ++formalIter, ++actualIter) {
         SgInitializedName *formalArg = *formalIter;
         SgExpression *actualArg = *actualIter;

         // Build the new local variable.
         // FIXME[Robb P. Matzke 2014-12-12]: we need a better way to generate a non-conflicting local variable name
         SgAssignInitializer* initializer = new SgAssignInitializer(SgNULL_FILE, actualArg, formalArg->get_type());
         ASSERT_not_null(initializer);
         initializer->set_endOfConstruct(SgNULL_FILE);
#if 1
         printf ("initializer = %p initializer->isTransformation() = %s \n",initializer,initializer->isTransformation() ? "true" : "false");
#endif
         SgName shadow_name(formalArg->get_name());
         shadow_name << "__" << ++gensym_counter;
         SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE, shadow_name, formalArg->get_type(), initializer);
         vardecl->set_definingDeclaration(vardecl);
         vardecl->set_endOfConstruct(SgNULL_FILE);
         vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE);
         vardecl->set_parent(funbody_copy);

         // Insert the new local variable into the (near) beginning of the to-be-inserted function body.  We insert them in the
         // order their corresponding actuals/formals appear, although the C++ standard does not require this order of
         // evaluation.
         SgInitializedName* init = vardecl->get_variables().back();
         inits.push_back(init);
         initializer->set_parent(init);
         init->set_scope(funbody_copy);
         funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + argNumber, vardecl);
         SgVariableSymbol* sym = new SgVariableSymbol(init);
         paramMap[formalArg] = sym;
         funbody_copy->insert_symbol(shadow_name, sym);
         sym->set_parent(funbody_copy->get_symbol_table());
     }

     // Similarly for "this". We create a local variable in the to-be-inserted function body that will be initialized with the
     // caller's "this".
     if (thisdecl) {
         thisdecl->set_parent(funbody_copy);
         thisinitname->set_scope(funbody_copy);
         funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl);
         SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname);
         funbody_copy->insert_symbol(thisname, thisSym);
         thisSym->set_parent(funbody_copy->get_symbol_table());
         ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder);
     }
     ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder);

     SgName end_of_inline_name = "rose_inline_end__";
     end_of_inline_name << ++gensym_counter;
     SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name);
     end_of_inline_label->set_endOfConstruct(SgNULL_FILE);

#if 0
     printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n");

  // Need to set the parent of funbody_copy to avoid error.
     funbody_copy->set_parent(funbody_raw->get_parent());

     printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy);

     printf ("funbody_raw->get_statements().size()  = %" PRIuPTR " \n",funbody_raw->get_statements().size());
     printf ("funbody_copy->get_statements().size() = %" PRIuPTR " \n",funbody_copy->get_statements().size());

     printf ("funbody_raw->get_symbol_table()->size()  = %d \n",(int)funbody_raw->get_symbol_table()->size());
     printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size());

     printf ("Output the symbol table for funbody_raw \n");
     funbody_raw->get_symbol_table()->print("debugging copy problem");

  // printf ("Output the symbol table for funbody_copy \n");
  // funbody_copy->get_symbol_table()->print("debugging copy problem");

     SgProject* project_copy = TransformationSupport::getProject(funbody_raw);
     ROSE_ASSERT(project_copy != NULL);

     const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000;
     generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH);
#endif

     funbody_copy->append_statement(end_of_inline_label);
     end_of_inline_label->set_scope(targetFunction);
     SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label);
     end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table());
     targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym);

     // To ensure that there is some statement after the label
     SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression());
     dummyStatement->set_endOfConstruct(SgNULL_FILE);
     funbody_copy->append_statement(dummyStatement);
     dummyStatement->set_parent(funbody_copy);
#if 0
     SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE);
     SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd);
     pragmaEndDecl->set_endOfConstruct(SgNULL_FILE);
     pragmaEnd->set_parent(pragmaEndDecl);
     pragmaEndDecl->set_definingDeclaration(pragmaEndDecl);
     funbody_copy->append_statement(pragmaEndDecl);
     pragmaEndDecl->set_parent(funbody_copy);
#endif

     ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy);
     replaceExpressionWithStatement(funcall, &previsitor);

     // Make sure the AST is consistent. To save time, we'll just fix things that we know can go wrong. For instance, the
     // SgAsmExpression.p_lvalue data member is required to be true for certain operators and is set to false in other
     // situations. Since we've introduced new expressions into the AST we need to adjust their p_lvalue according to the
     // operators where they were inserted.
     markLhsValues(targetFunction);
#ifdef NDEBUG
     AstTests::runAllTests(SageInterface::getProject());
#endif

#if 0
  // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag.
     ROSE_ASSERT(funcall != NULL);
     ROSE_ASSERT(funcall->get_parent() != NULL);
     ROSE_ASSERT(globalScope != NULL);
  // checkTransformedFlagsVisitor(funcall->get_parent());
     checkTransformedFlagsVisitor(globalScope);
#endif

  // DQ (4/7/2015): This fixes something I was required to fix over the weekend and which is fixed more directly, I think.
  // Mark the things we insert as being transformations so they get inserted into the output by backend()
     markAsTransformation(funbody_copy);

     return true;
   }
Exemple #12
0
//Generates SSA form numbers for the variables contained in *ex and attaches them as AstValueAttributes to the related SgNodes
//Assumption: *ex is located in in the inTrueBranch branch of the if node labeled *condLabel (These two arguments are required to generate the SSA form numbers)  
void SSAGenerator::processSgExpression(SgExpression* ex, Label* condLabel, bool inTrueBranch)
{
	SgIntVal* intVal = dynamic_cast<SgIntVal*>(ex);
	SgMinusOp* minusOp = dynamic_cast<SgMinusOp*>(ex);
	SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(ex);
	SgBinaryOp* binOp = dynamic_cast<SgBinaryOp*>(ex);
	SgFunctionCallExp* funcCall = dynamic_cast<SgFunctionCallExp*>(ex);
	
	if(intVal) //Int value
	{
		//Nothing needs to be done; Case is listed here to have a collection of all expected cases
	}
	else if(minusOp)
	{
		processSgExpression(minusOp->get_operand(), condLabel, inTrueBranch);
	}
	else if(varRef) //Reference to variable that is NOT on the left hand side of an assignment
	{
		//Assign number to variable
		string varName = varRef->get_symbol()->get_name().getString();
		int varNumber = currentNumber(varName, condLabel, inTrueBranch);  
		logger[Sawyer::Message::DEBUG] << "Current number for variable " << varName << ": " << varNumber << endl;
		AstValueAttribute<int>* varNumberAtt = new AstValueAttribute<int>(varNumber);
		varRef->setAttribute("SSA_NUMBER", varNumberAtt);	
	}
	else if(binOp) //Binary operation
	{	
		SgExpression* lhs = binOp->get_lhs_operand();
		SgExpression* rhs = binOp->get_rhs_operand();

		//Process right hand side first
		processSgExpression(rhs, condLabel, inTrueBranch);
		
		//Process left hand side second
		SgAssignOp* assignOp = dynamic_cast<SgAssignOp*>(binOp);	
		if(assignOp) //Assignment to a variable
		{
			//Assign new number to that variable  
			SgVarRefExp* lhsVarRef = dynamic_cast<SgVarRefExp*>(lhs);
			assert(lhsVarRef != NULL);
			processAssignmentTo(lhsVarRef, condLabel, inTrueBranch);
		}
		else //Arithmetic operation or boolean operation (or something unexpected)
		{
			processSgExpression(lhs, condLabel, inTrueBranch);	
		}	
		
	}
	else if(funcCall) //Call to a function
			  //RERS specific; Only two function call types are supported: 
			  //(1) scanf("%d",&...); 
			  //(2) __VERIFIER_error(RERSVerifierErrorNumber); The artificial bool variable RERSErrorOccured has to be updated 
	{
		string funcName = funcCall->getAssociatedFunctionSymbol()->get_name().getString();
		logger[Sawyer::Message::DEBUG] << "Call to function: " << funcName << endl;
		if(funcName == "scanf") //(1)
		{
			SgExprListExp* funcArgs = funcCall->get_args();
			SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions();
			SgExpressionPtrList::iterator i = funcArgsPtrs.begin();
			while(i != funcArgsPtrs.end())
			{
				SgAddressOfOp* addrOp = dynamic_cast<SgAddressOfOp*>(*i);
				if(addrOp) 
				{
					SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(addrOp->get_operand());
					if(varRef)
					{
						processAssignmentTo(varRef, condLabel, inTrueBranch);
					}
					else logger[Sawyer::Message::DEBUG] << "FOUND NO REFERENCE TO VARIABLE" << endl;
				}
				i++;	
			}	
		}
		else if(funcName == "__VERIFIER_error" && prepareReachabilityAnalysisZ3)
		{
			SgExprListExp* funcArgs = funcCall->get_args();
			SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions();
			assert(funcArgsPtrs.size() == 1);
			SgExpression* argument = *funcArgsPtrs.begin();
			SgIntVal* intArgument = dynamic_cast<SgIntVal*>(argument);
			assert(intArgument != NULL);
			if(intArgument->get_value() == RERSVerifierErrorNumber) //(2) 
			{
				int RERSErrorOccuredNumber = nextNumber("RERSErrorOccured", condLabel, inTrueBranch); 
				logger[Sawyer::Message::DEBUG] << "Next number for variable RERSErrorOccured: " << RERSErrorOccuredNumber << endl;
				AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(RERSErrorOccuredNumber);
				funcCall->setAttribute("SSA_NUMBER", numberAtt); 
			}
		}
		else logger[Sawyer::Message::DEBUG] << "Ignoring function call" << endl;
	}
	else //Unexpected
	{
		logger[Sawyer::Message::ERROR] << "ERROR: SgExpression could not be handled: " << ex->class_name() << endl;
		assert(false);
	}
}
Exemple #13
0
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);
    }
  }
}
void ControlDependenceGraph::_buildInterprocedural()
{


    // Go through the SGNODE dependence nodes and create the appropriate
    // call site nodes, entry nodes etc.

    SgFunctionDefinition *func = isSgFunctionDefinition(_head);

    ROSE_ASSERT(func != NULL);

    // First create the entry node for the procedure
    _interprocedural->procedureEntry.entry =
        new DependenceNode(DependenceNode::ENTRY, func->get_declaration());
    DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry);

    // Link the entry node up with all the nodes in the CDG which do not have
    // predecessors
    for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++)
    {
        DependenceNode *node = dynamic_cast < DependenceNode * >(*i);

        if ((node->numPredecessors() == 0) && (node != entry))
        {
            establishEdge(entry, node);
        }
    }

    // create a formal out return argument, control dependent on the entry
    // node
    string return_name = func->get_declaration()->get_name().str();

    return_name = return_name + " return";
    _interprocedural->procedureEntry.formal_return =
        new DependenceNode(DependenceNode::FORMALOUT, return_name);
    DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return);

    establishEdge(entry, formal_return);

    // for each of the arguments in the function parameter list, add a
    // formal-in and formal-out node
    SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList();
    SgInitializedNamePtrList params = paramlist->get_args();

    for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++)
    {
        SgInitializedName *name = *i;
        DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN,
                                                       name->get_name().str());
        DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT,
                                                        name->get_name().str());

        establishEdge(entry, createNode(formal_in));
        establishEdge(entry, createNode(formal_out));
        _interprocedural->procedureEntry.formal_in[name] = formal_in;
        _interprocedural->procedureEntry.formal_out[name] = formal_out;

        // To preserve the order of arguments, we insert them into arg_order
        _interprocedural->procedureEntry.arg_order.push_back(name);
    }

    // Now we go through each of the SgNodes in our CDG. If any of them
    // contain a function call, we want to build a call site node for them.
    map < SgNode *, DependenceNode * >::iterator sgnode_iterator;
    for (sgnode_iterator = _sgnode_map.begin();
         sgnode_iterator != _sgnode_map.end(); sgnode_iterator++)
    {
        SgNode *currnode = sgnode_iterator->first;

        list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode);
        if (calls.empty())
            continue;

        for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++)
        {
            SgFunctionCallExp *call = *i;

            // This needs to be replaced with some call graph analysis
            SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function());

            ROSE_ASSERT(func != NULL);
            SgName func_name = func->get_symbol()->get_name();

            InterproceduralInfo::CallSiteStructure callstructure;
            callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call);
            // the call site is control dependent on the statement (i.e. for
            // the call site to happen, the statement must be executed)
            DependenceNode *callsite = createNode(callstructure.callsite);

            // addLink(callsite, getNode(currnode));
            establishEdge(getNode(currnode), callsite);

            // create an actual out node for the return value, control
            // dependent on callsite
            string return_name = func_name.str();

            return_name = return_name + " return";
            callstructure.actual_return =
                new DependenceNode(DependenceNode::ACTUALOUT, return_name);
            DependenceNode *actual_return = createNode(callstructure.actual_return);

            establishEdge(callsite, actual_return);

            // For each argument in the function call, build an actual_in and
            // actual_out, control dependent on callsite
            SgExpressionPtrList args = call->get_args()->get_expressions();

            for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++)
            {
                SgExpression *arg = *j;
                DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg);
                DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg);

                establishEdge(callsite, createNode(actual_in));
                establishEdge(callsite, createNode(actual_out));
                callstructure.actual_in[arg] = actual_in;
                callstructure.actual_out[arg] = actual_out;

                // To preserve the order of expressions in the parameter list, 
                // 
                // we insert them into expr_order
                callstructure.expr_order.push_back(arg);
            }

            // add the callstructure to interprocedural info
            _interprocedural->callsite_map[call] = callstructure;
        }
    }
}
Exemple #15
0
Fichier : mlm.cpp Projet : 8l/rose
void mlmTransform::transformCallExp(SgCallExpression* callExp)
{
    ROSE_ASSERT(callExp);
    SgFunctionRefExp* funcName = isSgFunctionRefExp(callExp->get_function());
    if(!funcName) 
      return;
    SgExprListExp* funcArgList = callExp->get_args();
    SgExpressionPtrList argList = funcArgList->get_expressions();
    SgScopeStatement* scope = getScope(callExp);         
    //cout << funcName->get_symbol()->get_name() << endl;

    /** if it is malloc, search for the mlm attribute and append the memory level **/
    if(strncmp("malloc",funcName->get_symbol()->get_name().str(),6) == 0)
    {
      if(argList.size() != 1)  return;
      SgExprListExp* funcArgList = callExp->get_args();

      // check if LHS of malloc has an attribute assigned
      SgNode* parentNode = callExp->get_parent();
      // parent node can be a casting expression
      if(isSgCastExp(parentNode))
      {
        parentNode = parentNode->get_parent();
      }
      // the mlm attribute
      AstAttribute* attr = NULL;
      // So far we spot two candidates for parentNode that we need to transform
      if(isSgAssignOp(parentNode))
      {
        SgAssignOp* assignOp = isSgAssignOp(parentNode);
        SgExpression* lhs = isSgExpression(assignOp->get_lhs_operand());
        if(!isSgVarRefExp(lhs))
        {
          //cout << "lhs:" << assignOp->get_lhs_operand()->class_name() << endl;

          // if pointer is packaged inside a struct, then we need to look down in lhs.
          if(isSgDotExp(lhs))
          {
            lhs = isSgDotExp(lhs)->get_rhs_operand();
          }
        }
        SgVarRefExp* lhsVarRef = isSgVarRefExp(lhs);
        ROSE_ASSERT(lhsVarRef);
        SgSymbol* symbol = lhsVarRef->get_symbol();
        ROSE_ASSERT(symbol);
        //retrieve the attribute from symbol
        attr = symbol->getAttribute("mlmAttribute");
        //cout << "LHS symbol name: " << symbol->get_name() << endl;
      }
      else if(isSgAssignInitializer(parentNode))
      {
        SgInitializedName* initName = isSgInitializedName(parentNode->get_parent());
        ROSE_ASSERT(initName);
        SgSymbol* symbol = initName->get_symbol_from_symbol_table();
        if(!symbol) return;
        ROSE_ASSERT(symbol);
        //retrieve the attribute from symbol
        attr = symbol->getAttribute("mlmAttribute");
        //cout << "Initialized symbol name: " << symbol->get_name() << endl;
      }
      else
      {
        // do nothing because no attribute assigned or we always set to default
      }
      // if there is a mlm attribute attached to the symbol, then create new malloc
      if(attr)
      {
        mlmAttribute* mlmAttr = dynamic_cast<mlmAttribute*> (attr);
        SgExprListExp* funcArgList = callExp->get_args();
        funcArgList->append_expression(buildIntVal(mlmAttr->getMemType()));
        replaceExpression(callExp, buildFunctionCallExp("mlm_malloc",deepCopy(callExp->get_type()),deepCopy(funcArgList),getScope(callExp)));
      }
    }
    else if(strncmp("memcpy",funcName->get_symbol()->get_name().str(),6) == 0)
    {
//      cout << "replacing memcpy" << endl;
      if(argList.size() != 3)  return;
      Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree(funcArgList, V_SgVarRefExp);
      SgVarRefExp* dst = isSgVarRefExp(varList[0]);
      SgVarRefExp* src = isSgVarRefExp(varList[1]);
      AstAttribute* attrDst = dst->get_symbol()->getAttribute("mlmAttribute");
      AstAttribute* attrSrc = src->get_symbol()->getAttribute("mlmAttribute");
      mlmAttribute* mlmAttrDst =  dynamic_cast<mlmAttribute*>(attrDst);
      mlmAttribute* mlmAttrSrc =  dynamic_cast<mlmAttribute*>(attrSrc);
//      if((mlmAttrDst && !mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() < mlmAttrDst->getMemType())))
//      {
//        replaceExpression(callExp, buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),true);
//        DeletepragmasList2.push_back(callExp);
//      }
//
//      else if((!mlmAttrDst && mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() > mlmAttrDst->getMemType())))

// 09/30/14 Following Simon's suggestion, we always insert wait for the mlm_memcpy
//      {
         string tagName = generateUniqueVariableName(scope,"copy_tag");
         SgVariableDeclaration* newDecl = buildVariableDeclaration(tagName,
                                          buildOpaqueType("mlm_Tag",getGlobalScope(callExp)), 
                                          buildAssignInitializer(buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope)));
         SgExprStatement* waitStmt = buildFunctionCallStmt("mlm_waitComplete",
                                                           buildVoidType(),
                                                           buildExprListExp(buildVarRefExp(tagName,scope)),
                                                           scope); 
         insertStatement(getEnclosingStatement(callExp),newDecl,true);
         insertStatement(getEnclosingStatement(callExp),waitStmt,true);
         removeStatement(getEnclosingStatement(callExp));
//      }
    }
    else if(strncmp("free",funcName->get_symbol()->get_name().str(),4) == 0)
    {
//      cout << "replacing free" << endl;
      if(argList.size() != 1)  return;
      SgExpression* varExp = isSgExpression(argList[0]);
//cout << "exp:" << varExp->class_name() << endl;
      if(!isSgVarRefExp(varExp))
      {
        if(isSgCastExp(varExp))
        {
          varExp = isSgCastExp(varExp)->get_operand_i();
        }
        // if pointer is packaged inside a struct, then we need to look down in lhs.
        if(isSgDotExp(varExp))
        {
          varExp = isSgDotExp(varExp)->get_rhs_operand();
        }
      }
      SgVarRefExp* varRef = isSgVarRefExp(varExp);
      ROSE_ASSERT(varRef);
      AstAttribute* attr = varRef->get_symbol()->getAttribute("mlmAttribute");
      if(attr)
      {
        replaceExpression(callExp, buildFunctionCallExp("mlm_free",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),false);
      }
    }

}
Exemple #16
0
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
}
/*! 
  * \author Markus Schordan
  * \date 2014.
 */
void SPRAY::IntervalTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element) {
  // uses and defs in argument-expressions
  for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) {
    transferExpression(lab,*i,element);
  }
}