示例#1
0
 void traverse_tree(typename tree_traits<Tree>::node_descriptor v,
                    Tree& t, TreeVisitor visitor)
 {
   visitor.preorder(v, t);
   typename tree_traits<Tree>::children_iterator i, end;
   tie(i, end) = children(v, t);
   if (i != end) {
     traverse_tree(*i++, t, visitor);
     visitor.inorder(v, t);
     while (i != end)
       traverse_tree(*i++, t, visitor);
   } else
     visitor.inorder(v, t);
   visitor.postorder(v, t);
 }
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);
        }
      }
    }
  }
}
示例#3
0
void Callback::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#4
0
void Variable::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#5
0
void Parameter::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#6
0
void BinaryExpression::accept(TreeVisitor& v)
{
	v.visit(*this);
}
示例#7
0
 void Accept(TreeVisitor<charT, AddressTable, sentinel>& visitor) { visitor.VisitLocation(this); }
示例#8
0
void ForStatement::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#9
0
void ScriptImport::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#10
0
void VectorExpression::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#11
0
void Module::accept(TreeVisitor& v)
{
	v.visit(*this);
}
示例#12
0
void Function::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#13
0
void ModuleImport::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#14
0
void CodeDoc::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#15
0
void RangeExpression::accept(TreeVisitor& v)
{
	v.visit(this);
}
示例#16
0
void IfElseStatement::accept(TreeVisitor& v)
{
	v.visit(this);
}