Esempio n. 1
0
// DQ (10/6/2007): Added fixup function to set scopes not set properly by the ROSETTA generated copy!
void
SgFunctionParameterList::fixupCopy_symbols(SgNode* copy, SgCopyHelp & help) const
   {
#if DEBUG_FIXUP_COPY
     printf ("Inside of SgFunctionParameterList::fixupCopy_symbols() for %p = %s copy = %p \n",this,this->class_name().c_str(),copy);
#endif

  // Also call the base class version of the fixupCopycopy() member function
     SgDeclarationStatement::fixupCopy_symbols(copy,help);

     SgFunctionParameterList* copyFunctionParameterList = isSgFunctionParameterList(copy);
     ROSE_ASSERT(copyFunctionParameterList != NULL);

     const SgInitializedNamePtrList & parameterList_original = this->get_args();
     SgInitializedNamePtrList & parameterList_copy           = copyFunctionParameterList->get_args();

     SgInitializedNamePtrList::const_iterator i_original = parameterList_original.begin();
     SgInitializedNamePtrList::iterator i_copy           = parameterList_copy.begin();

  // Iterate over both lists to match up the correct pairs of SgInitializedName objects
     while ( (i_original != parameterList_original.end()) && (i_copy != parameterList_copy.end()) )
        {
          (*i_original)->fixupCopy_symbols(*i_copy,help);

          i_original++;
          i_copy++;
        }
   }
Esempio n. 2
0
SgFunctionParameterList * SageUtils::buildEmptyParameterList() {
    SgFunctionParameterList *parameterList = new SgFunctionParameterList();
    ROSE_ASSERT (parameterList);
    parameterList->set_definingDeclaration (NULL);
    parameterList->set_firstNondefiningDeclaration(parameterList);
    SageInterface::setOneSourcePositionForTransformation(parameterList);
    return parameterList;
}
Esempio n. 3
0
void PreAndPostOrderTraversal::preOrderVisit(SgNode* n) {

        SgFunctionDeclaration * dec = isSgFunctionDeclaration(n);
        if (dec != NULL) {
                cout << "Found function declaration " << dec->get_name().getString();
                Sg_File_Info * start = dec->get_startOfConstruct();
                Sg_File_Info * end = dec->get_endOfConstruct();
                if(start->isCompilerGenerated()) {
                        cout << ", which is compiler-generated" << endl;
                } else {
                        cout << " in file " << start->get_raw_filename() << ", " << start->get_file_id() << " from line " << 
                            start->get_line() << ", col " << start->get_col() << " to line " << 
                            end->get_line() << ", col " << end->get_col() << endl;
                }
                SgFunctionType * type = dec->get_type();
                SgType * retType = type->get_return_type();
        cout << "Return type: " << retType->unparseToString() << endl;
        SgFunctionParameterList * params = dec->get_parameterList();
        SgInitializedNamePtrList & ptrList = params->get_args();
        if(!ptrList.empty()) {
            cout << "Parameter types: ";
            for(SgInitializedNamePtrList::iterator j = ptrList.begin(); j != ptrList.end(); j++) {
                SgType * pType = (*j)->get_type();
                cout << pType->unparseToString() << " ";
            }
            cout << endl;
        }
        cout << "Linkage: " << dec->get_linkage() << endl;
               cout << endl;
        }


        SgFunctionDefinition * def = isSgFunctionDefinition(n);
        if (def != NULL) {
                cout << "Found function definition " << def->get_declaration()->get_name().getString();
                Sg_File_Info * start = def->get_startOfConstruct();
                Sg_File_Info * end = def->get_endOfConstruct();
                if(start->isCompilerGenerated()) {
                        cout << ", which is compiler-generated" << endl;
                } else {
                        cout << " in file " << start->get_raw_filename() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl;
                SgBasicBlock * body = def->get_body();
        Sg_File_Info * bodyStart = body->get_startOfConstruct();
        Sg_File_Info * bodyEnd =   body->get_endOfConstruct();
        cout << "Function body from line " << bodyStart->get_line() << ", col " << bodyStart->get_col() << " to line " << bodyEnd->get_line() << ", col " << bodyEnd->get_col() << endl; 
 }
        cout << endl;
        }
}
Esempio n. 4
0
SgFunctionParameterList * Kernel<Annotation, Runtime>::createParameterList() const {
  const std::list<SgVariableSymbol *> & params = getArguments().parameters;
  const std::list<SgVariableSymbol *> & scalars = getArguments().scalars;
  const std::list<Data<DLX::KLT::Annotation<DLX::TileK::language_t> > *> & datas = getArguments().datas;

  std::list<SgVariableSymbol *>::const_iterator it_var_sym;
  std::list<Data<DLX::KLT::Annotation<DLX::TileK::language_t> > *>::const_iterator it_data;

  SgFunctionParameterList * result = SageBuilder::buildFunctionParameterList();

  result->append_arg(SageBuilder::buildInitializedName("param",  SageBuilder::buildPointerType(SageBuilder::buildIntType()), NULL));
  result->append_arg(SageBuilder::buildInitializedName("data",   SageBuilder::buildPointerType(SageBuilder::buildPointerType(SageBuilder::buildVoidType())), NULL));
  result->append_arg(SageBuilder::buildInitializedName("scalar", SageBuilder::buildPointerType(SageBuilder::buildPointerType(SageBuilder::buildVoidType())), NULL));

  result->append_arg(Runtime::kernel_api.createContext());

  return result;
}
Esempio n. 5
0
/**
 * Processes parameters passed to a function
 * @param functionDeclaration
 */
void AOSModule::processParameters(SgFunctionDeclaration *functionDeclaration) {
	PrintUtil::printFunctionStart("AOSModule::processParameters");

	SgBasicBlock *functionBody =
			functionDeclaration->get_definition()->get_body();
	ROSE_ASSERT(functionBody);

	SgFunctionParameterList *parameters =
			functionDeclaration->get_parameterList();
	ROSE_ASSERT (parameters);

	SgInitializedNamePtrList & parameterList = parameters->get_args();
	foreach(SgInitializedName * initializedName, parameterList)
	{
		SgType *paramType = initializedName->get_type();
		string type = TransformationSupport::getTypeName(paramType);

		trace << " Function Parameter :" << initializedName->get_name()
				<< " Type: " << type << endl;

		Field *metaField = meta->getField(initializedName->get_name().str());
		if (metaField == NULL)
			continue;
		trace << " Meta Field found " << endl;

		if(!checkExtendedVariable(initializedName))
			continue;

		// Set the appropriate type as there may be
		// parameters with const keyword which causes exception
		// in creating structs at runtime
		initializedName->set_type(buildParameterType(metaField));

		// if struct exist continue
		if (!isBuildStruct(metaField))
			continue;

		// Build a structure at the start for function
		buildStructAtStart(metaField, functionBody);
	}
void
FortranCUDAUserSubroutine::createStatements ()
{
  using namespace SageInterface;
  using boost::iequals;
  using std::string;
  using std::vector;
  
  class TreeVisitor: public AstSimpleProcessing
  {
    private:
    /*
     * ======================================================
     * The recursive visit of a user subroutine populates
     * this vector with successive function calls which are
     * then appended after the visit
     * ======================================================
     */            
    vector < SgProcedureHeaderStatement * > calledRoutines;

    public:

      vector < SgProcedureHeaderStatement * > getCalledRoutinesInStatement()
      {
        return calledRoutines;
      }
      
      TreeVisitor ()
      {
      }

      virtual void
      visit (SgNode * node)
      {
        SgExprStatement * isExprStatement = isSgExprStatement ( node );
        if ( isExprStatement != NULL )
        {      
          SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() );
        
          if ( functionCallExp != NULL )
          {
            string const
                calleeName =
                    functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString ();

            Debug::getInstance ()->debugMessage ("Found function call in user subroutine "
                + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__);

            /*
             * ======================================================
             * As we are in fortran, all user subroutines must be
             * SgProcedureHeaderStatements = subroutines and not
             * functions. This might be extended to cover also 
             * functions in the future (?). Probably not in OP2
             * ======================================================
             */
            SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( 
              functionCallExp->getAssociatedFunctionDeclaration() );

            calledRoutines.push_back ( isProcedureHeaderStatement );
          }
        }
      }
  };
  
  Debug::getInstance ()->debugMessage ("User subroutine: outputting and modifying statements",
      Debug::FUNCTION_LEVEL, __FILE__, __LINE__);

  SgFunctionParameterList * originalParameters =
      originalSubroutine->get_parameterList ();

  vector <SgStatement *> originalStatements =
      originalSubroutine->get_definition ()->get_body ()->get_statements ();

  for (vector <SgStatement *>::iterator it = originalStatements.begin (); it
      != originalStatements.end (); ++it)
  {      
 
    SgExprStatement * isExprStatement = isSgExprStatement ( *it );
    if ( isExprStatement != NULL )
    {      
      SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() );
    
      if ( functionCallExp != NULL )
      {
        string const
            calleeName =
                functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString ();

        Debug::getInstance ()->debugMessage ("Found function call in user subroutine "
            + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__);

        /*
         * ======================================================
         * As we are in fortran, all user subroutines must be
         * SgProcedureHeaderStatements = subroutines and not
         * functions. This might be extended to cover also 
         * functions in the future (probably not in OP2)
         * ======================================================
         */            
        SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( 
          functionCallExp->getAssociatedFunctionDeclaration() );
            
        calledRoutines.push_back ( isProcedureHeaderStatement );
      }
    }

    SgVariableDeclaration * isVariableDeclaration = isSgVariableDeclaration (
        *it);

    if (isVariableDeclaration == NULL)
    { 
      /*
       * ======================================================
       * Do not append use statement, because other subroutines
       * are directly appended to the CUDA module
       * ======================================================
       */                  
      SgUseStatement * isUseStmt = isSgUseStatement ( *it );
      if (isUseStmt != NULL)
        {
          Debug::getInstance ()->debugMessage (
                "Not appending use statement",
                Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);
        }
      else
      {
        Debug::getInstance ()->debugMessage (
              "Appending (non-variable-declaration) statement",
              Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);

        appendStatement (*it, subroutineScope);

        /*
         * ======================================================
         * Recursively look for subroutine calls inside shallow
         * nodes in the routines (e.g. when a call is inside an 
         * if). After the visit get the generated vector of names
         * and append it to the userSubroutine vector
         * ======================================================
         */                  
        TreeVisitor * visitor = new TreeVisitor ();
	  
        visitor->traverse (*it, preorder);
          
        Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__);

          
        vector < SgProcedureHeaderStatement * > deepStatementCalls = visitor->getCalledRoutinesInStatement ();
        vector < SgProcedureHeaderStatement * >::iterator itDeepCalls;
        for (itDeepCalls = deepStatementCalls.begin(); itDeepCalls != deepStatementCalls.end(); ++itDeepCalls)
          calledRoutines.push_back (*itDeepCalls);
      
        Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__);
      }
    }
    else
    {
      Debug::getInstance ()->debugMessage ("Appending variable declaration",
          Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);

      unsigned int OP_DAT_ArgumentGroup = 1;

      for (SgInitializedNamePtrList::iterator variableIt =
          isVariableDeclaration->get_variables ().begin (); variableIt
          != isVariableDeclaration->get_variables ().end (); ++variableIt)
      {
        string const variableName = (*variableIt)->get_name ().getString ();

        SgType * type = (*variableIt)->get_typeptr ();

        /*
         * ======================================================
         * Specification of "value" attribute is only
         * for user kernels. Our call convention is that
         * in all deeper level calls we always pass parameters
         * by reference (see else branch below)
         * ======================================================
         */                  
        
        bool isFormalParamater = false;
	
        for (SgInitializedNamePtrList::iterator paramIt =
            originalParameters->get_args ().begin (); paramIt
            != originalParameters->get_args ().end (); ++paramIt, ++OP_DAT_ArgumentGroup)
        {
          string const formalParamterName = (*paramIt)->get_name ().getString ();

          if (iequals (variableName, formalParamterName))
          {
            isFormalParamater = true;

            if (parallelLoop->isIndirect (OP_DAT_ArgumentGroup)
                && parallelLoop->isRead (OP_DAT_ArgumentGroup))
            {
              Debug::getInstance ()->debugMessage ("'" + variableName
                  + "' is an INDIRECT formal parameter which is READ",
                  Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);

              SgVariableDeclaration * variableDeclaration;
              if ( isUserKernel == true )
                variableDeclaration =
                      FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter (
                          variableName, type, subroutineScope,
                          formalParameters, 0);
              else
                  variableDeclaration =
                      FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter (
                          variableName, type, subroutineScope,
                          formalParameters, 0);

                ROSE_ASSERT ( variableDeclaration != NULL );
            }
            else if (parallelLoop->isGlobal (OP_DAT_ArgumentGroup)                     
                     && parallelLoop->isRead (OP_DAT_ArgumentGroup))
            {
              Debug::getInstance ()->debugMessage ("'" + variableName
                + "' is a GLOBAL formal parameter which is READ",
                Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);

                SgVariableDeclaration * variableDeclaration =
                  FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter (
                    variableName, type, subroutineScope, formalParameters, 0);
            }
            else
            {
              Debug::getInstance ()->debugMessage ("'" + variableName
                  + "' is a formal parameter "
                  + parallelLoop->getOpDatInformation (OP_DAT_ArgumentGroup),
                  Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__);

              if ( isUserKernel == true )
                SgVariableDeclaration * variableDeclaration =
                  FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter (
                    variableName, type, subroutineScope, formalParameters, 0);
              else
                SgVariableDeclaration * variableDeclaration =
                  FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter (
                    variableName, type, subroutineScope, formalParameters, 0);
            }
          }
        }
          
        if (isFormalParamater == false)
        {
          Debug::getInstance ()->debugMessage ("'" + variableName
            + "' is NOT a formal parameter", Debug::HIGHEST_DEBUG_LEVEL,
            __FILE__, __LINE__);

          SgVariableDeclaration * variableDeclaration =
            FortranStatementsAndExpressionsBuilder::appendVariableDeclaration (
            variableName, type, subroutineScope);
        }
      }
    }
  }
}
string
PrefixSuffixGenerationTraversal::DeclarationOrCommentListElement::
generateDeclarationString ( SgDeclarationStatement* declaration ) const
   {
  // This function generates a string for a declaration. The string is required for 
  // the intermediate file to make sure that all transformation code will compile 
  // (since it could depend on declarations defined within the code).

  // Details:
  //   1) Only record declarations found within the source file (exclude all header files 
  //      since they will be seen when the same header files are included).
  //   2) Resort the variable declarations to remove redundent entries.
  //        WRONG: variable declarations could have dependences upon class declarations!
  //   3) Don't sort all declarations since some could have dependences.
  //        a) class declarations
  //        b) typedefs
  //        c) function declarations
  //        d) template declarations
  //        e) variable definition???

      ROSE_ASSERT (this != NULL);
      ROSE_ASSERT ( declaration != NULL );
      string declarationString;

   // Build a SgUnparse_Info object to represent formatting options for
   // this statement (use the default values).
      SgUnparse_Info info;

   // exclude comments
      info.set_SkipComments();

   // exclude all CPP directives (since they have already been evaluated by the front-end)
      info.set_SkipCPPDirectives();

      switch ( declaration->variantT() )
        {
       // Enum declarations should not skip their definition since 
       // this is where the constants are declared.
          case V_SgEnumDeclaration:

          case V_SgVariableDeclaration:
          case V_SgTemplateDeclaration:
          case V_SgTypedefDeclaration:
            // Need to figure out if a forward declaration would work or be 
            // more conservative and always output the complete class definition.

            // turn off output of initializer values
               info.set_SkipInitializer();
            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;

          case V_SgClassDeclaration:
            // Need to figure out if a forward declaration would work or be 
            // more conservative and always output the complete class definition.

            // turn off the generation of the function definitions only 
            // (we still want the restof the class definition since these 
            // define all member data and member functions).
            // info.set_SkipClassDefinition();
               info.set_SkipFunctionDefinition();
               info.set_AddSemiColonAfterDeclaration();

            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;

       // For functions just output the declaration and skip the definition
       // (This also avoids the generation of redundent definitions since the 
       // function we are in when we generate all declarations would be included).
          case V_SgMemberFunctionDeclaration:
          case V_SgFunctionDeclaration:
             {
            // turn off the generation of the definition
               info.set_SkipFunctionDefinition();
               info.set_AddSemiColonAfterDeclaration();

            // output the declaration as a string
               declarationString = globalUnparseToString(declaration,&info);
               break;
             }

          case V_SgFunctionParameterList:
             {
            // Handle generation of declaration strings this case differnetly from unparser
            // since want to generate declaration strings and not function parameter lists
            // (function parameter lists would be delimited by "," while declarations would
            // be delimited by ";").
               SgFunctionParameterList* parameterListDeclaration = dynamic_cast<SgFunctionParameterList*>(declaration);
               ROSE_ASSERT (parameterListDeclaration != NULL);
               SgInitializedNamePtrList & argList = parameterListDeclaration->get_args();
               SgInitializedNamePtrList::iterator i;
               for (i = argList.begin(); i != argList.end(); i++)
                  {
                    printf ("START: Calling unparseToString on type! \n");
                    ROSE_ASSERT((*i) != NULL);
                    ROSE_ASSERT((*i)->get_type() != NULL);
                    string typeNameString = (*i)->get_type()->unparseToString();
                    printf ("DONE: Calling unparseToString on type! \n");

                    string variableName;
                    if ( (*i)->get_name().getString() != "")
                       {
                         variableName   = (*i)->get_name().getString();
                         declarationString += typeNameString + " " + variableName + "; ";
                       }
                      else
                       {
                      // Don't need the tailing ";" if there is no variable name (I think)
                         declarationString += typeNameString + " ";
                       }
                  }
               break;
             }

       // ignore this case ... not really a declaration
          case V_SgCtorInitializerList:
            // printf ("Ignore the SgCtorInitializerList (constructor initializer list) \n");
               break;

          case V_SgVariableDefinition:
               printf ("ERROR: SgVariableDefinition nodes not used in AST \n");
               ROSE_ABORT();
               break;

       // default case should always be an error
          default:
               printf ("Default reached in AST_Rewrite::AccumulatedDeclarationsAttribute::generateDeclarationString() \n");
               printf ("     declaration->sage_class_name() = %s \n",declaration->sage_class_name());
               ROSE_ABORT();
               break;
        }

  // Add a space to make it easier to read (not required)
     declarationString += " ";

  // printf ("For this scope: declarationString = %s \n",declarationString.c_str());

     return declarationString;
   }
/**
 * \brief Return true if methodDecl overrides virtualMethodDecl.
 * \param methodDecl  a method declaration.
 * \param virtualMethodDecl a method declaration.
 * \return Returns true if virtualMethodDecl is declared as a virtual
 *         method and methodDecl has the same type signature and name
 *         as virtualMethodDecl.  
 * 
 * NB:  It is assumed that the class defining virtualMethodDecl is a base
 *      class of the class defining methodDecl.
 */
bool
methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, 
			     SgMemberFunctionDeclaration *virtualMethodDecl)
{
  if ( !isVirtual(virtualMethodDecl) )
    return false;

  //  std::cout << "looks virtual" << std::endl;

#if 0
  // Hmmm ... couldn't we just compare mangled names?
  // No, we can't because this includes the scope info, which will
  // differ between classes.
  std::cout << "methodDecl: " << methodDecl->get_mangled_name().str() << std::endl;
  std::cout << "virtualMethodDecl: " << virtualMethodDecl->get_mangled_name().str() << std::endl;
  return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() );

#else
  if ( methodDecl->get_name() != virtualMethodDecl->get_name() )
    return false;
  
  SgType *methodReturnType = methodDecl->get_orig_return_type();
  SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type();

  if ( methodReturnType != virtualMethodReturnType )
    return false;

  int numMethodParams = 0;
  int numVirtualMethodParams = 0;

  SgFunctionParameterList *methodParameterList = 
    methodDecl->get_parameterList(); 

  if (methodParameterList != NULL) {
    numMethodParams = methodParameterList->get_args().size();
  }

  SgFunctionParameterList *virtualMethodParameterList = 
    virtualMethodDecl->get_parameterList(); 

  if (virtualMethodParameterList != NULL) {
    numVirtualMethodParams = virtualMethodParameterList->get_args().size();
  }

  if ( numMethodParams != numVirtualMethodParams )
    return false;

  if ( numMethodParams == 0 )
    return true;

  const SgInitializedNamePtrList &methodFormalParams = 
    methodParameterList->get_args(); 
  const SgInitializedNamePtrList &virtualMethodFormalParams = 
    virtualMethodParameterList->get_args(); 
  SgInitializedNamePtrList::const_iterator methodIt;
  SgInitializedNamePtrList::const_iterator virtualMethodIt;
  for(methodIt = methodFormalParams.begin(), 
	virtualMethodIt = virtualMethodFormalParams.begin();
      methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { 
      
      SgInitializedName* methodFormalParam = *methodIt;  
      ROSE_ASSERT(methodFormalParam != NULL); 

      SgInitializedName* virtualMethodFormalParam = *virtualMethodIt;  
      ROSE_ASSERT(virtualMethodFormalParam != NULL); 
      
      if ( methodFormalParam->get_type() != 
	   virtualMethodFormalParam->get_type() )
	return false;

  }

  return true;
#endif
}
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;
        }
    }
}
/**
 * \brief Return true if methodDecl overrides virtualMethodDecl.
 * \param methodDecl  a method declaration.
 * \param virtualMethodDecl a method declaration.
 * \return Returns true if virtualMethodDecl is declared as a virtual
 *         method and methodDecl has the same type signature and name
 *         as virtualMethodDecl.  
 * 
 * NB:  It is assumed that the class defining virtualMethodDecl is a base
 *      class of the class defining methodDecl.
 */
bool
methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, 
			     SgMemberFunctionDeclaration *virtualMethodDecl)
{
  if ( !isVirtual(virtualMethodDecl) )
    return false;

#if 1
  // Hmmm ... couldn't we just compare mangled names?
  return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() );

#else
  if ( methodDecl->get_name() != virtualMethodDecl->get_name() )
    return false;
  
  SgType *methodReturnType = methodDecl->get_orig_return_type();
  SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type();

  if ( methodReturnType != virtualMethodReturnType )
    return false;

  int numMethodParams = 0;
  int numVirtualMethodParams = 0;

  SgFunctionParameterList *methodParameterList = 
    methodDecl->get_parameterList(); 

  if (methodParameterList != NULL) {
    numMethodParams = methodParameterList->get_args().size();
  }

  SgFunctionParameterList *virtualMethodParameterList = 
    virtualMethodDecl->get_parameterList(); 

  if (virtualMethodParameterList != NULL) {
    numVirtualMethodParams = virtualMethodParameterList->get_args().size();
  }

  if ( numMethodParams != numVirtualMethodParams )
    return false;

  if ( numMethodParams == 0 )
    return true;

  const SgInitializedNamePtrList &methodFormalParams = 
    methodParameterList->get_args(); 
  const SgInitializedNamePtrList &virtualMethodFormalParams = 
    virtualMethodParameterList->get_args(); 
  SgInitializedNamePtrList::const_iterator methodIt;
  SgInitializedNamePtrList::const_iterator virtualMethodIt;
  for(methodIt = methodFormalParams.begin(), 
	virtualMethodIt = virtualMethodFormalParams.begin();
      methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { 
      
      SgInitializedName* methodFormalParam = *methodIt;  
      ROSE_ASSERT(methodFormalParam != NULL); 

      SgInitializedName* virtualMethodFormalParam = *virtualMethodIt;  
      ROSE_ASSERT(virtualMethodFormalParam != NULL); 
      
      if ( methodFormalParam->get_type() != 
	   virtualMethodFormalParam->get_type() )
	return false;

  }

  return true;
#endif
}