Example #1
0
SgVariableDeclaration*
buildStructVariable ( SgScopeStatement* scope,
              vector<SgType*> memberTypes, vector<string> memberNames,
              string structName = "", string varName = "", SgAggregateInitializer *initializer = NULL )
   {
     ROSE_ASSERT(memberTypes.size() == memberNames.size());
     SgClassDeclaration* classDeclaration = buildClassDeclarationAndDefinition(structName,scope);
     vector<SgType*>::iterator typeIterator       = memberTypes.begin();
     vector<string>::iterator  memberNameIterator = memberNames.begin();
     while (typeIterator != memberTypes.end())
        {
       // printf ("Adding data member type = %s variable name = %s \n",(*typeIterator)->unparseToString().c_str(),memberNameIterator->c_str());
          SgVariableDeclaration* memberDeclaration = new SgVariableDeclaration(SOURCE_POSITION,*memberNameIterator,*typeIterator,NULL);
          memberDeclaration->set_endOfConstruct(SOURCE_POSITION);

          classDeclaration->get_definition()->append_member(memberDeclaration);

          memberDeclaration->set_parent(classDeclaration->get_definition());
        // Liao (2/13/2008) scope and symbols for member variables
          SgInitializedName* initializedName = *(memberDeclaration->get_variables().begin());
          initializedName->set_file_info(SOURCE_POSITION);
          initializedName->set_scope(classDeclaration->get_definition());

        // set nondefning declaration pointer
         memberDeclaration->set_firstNondefiningDeclaration(memberDeclaration);

         SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName);
         classDeclaration->get_definition()->insert_symbol(*memberNameIterator,variableSymbol);

          typeIterator++;
          memberNameIterator++;
        }

     SgClassType* classType = new SgClassType(classDeclaration->get_firstNondefiningDeclaration());
     SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(SOURCE_POSITION,varName,classType,initializer);
     variableDeclaration->set_endOfConstruct(SOURCE_POSITION);

   //Liao (2/13/2008) scope and symbols for struct variable
     SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin());
     initializedName->set_file_info(SOURCE_POSITION);
     initializedName->set_scope(scope);

     SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName);
     scope->insert_symbol(varName,variableSymbol);

  //set nondefining declaration 
    variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration);

  // This is required, since it is not set in the SgVariableDeclaration constructor
     initializer->set_parent(variableDeclaration);

     variableDeclaration->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true);
     variableDeclaration->set_baseTypeDefiningDeclaration(classDeclaration->get_definingDeclaration());

     classDeclaration->set_parent(variableDeclaration);

     return variableDeclaration;
   }
Example #2
0
DoxygenFile::DoxygenFile(SgProject *prj, string filename)
{
    Sg_File_Info *info = new Sg_File_Info(filename, 0, 0);

    SgInitializedName *iname = new SgInitializedName;
    stringstream sname;
    sname << "SAGE_Doxygen_Dummy_" << rand();
    iname->set_name(sname.str());
    iname->set_type(new SgTypeInt);
    iname->set_file_info(info);
    iname->get_storageModifier().setExtern();

    SgVariableDeclaration *decl = new SgVariableDeclaration;
    decl->get_variables().push_back(iname);
    decl->set_startOfConstruct(info);
    decl->set_endOfConstruct(info);
    decl->get_declarationModifier().get_storageModifier().setExtern();
    iname->set_parent(decl);
    iname->set_prev_decl_item(iname);

    // SgGlobal *glob = prj->get_file(0).get_globalScope();
    SgSourceFile* sourceFile = isSgSourceFile(prj->get_fileList()[0]);
    ROSE_ASSERT(sourceFile != NULL);
    SgGlobal *glob = sourceFile->get_globalScope();

    // glob->insertStatementInScope(decl, true);
    glob->get_declarations().insert(glob->get_declarations().begin(),decl);
    decl->set_parent(glob);
    SgVariableSymbol* variableSymbol = new SgVariableSymbol(iname);
    glob->insert_symbol(sname.str(),variableSymbol);


    decl->set_parent(glob);
    std::cout << "Before complete string." << std::endl;
    //glob->append_declaration(decl);
    iname->set_scope(glob);

    decl->unparseToCompleteString();

    std::cout << "After complete string." << std::endl;

    commentParent = decl;
    printf("commentParent = %p\n", commentParent);
}
void
SimpleInstrumentation::visit ( SgNode* astNode )
   {
     SgBasicBlock* block = isSgBasicBlock(astNode);
     if (block != NULL)
        {
       // Mark this as a transformation (required)
          Sg_File_Info* sourceLocation = Sg_File_Info::generateDefaultFileInfoForTransformationNode();
          ROSE_ASSERT(sourceLocation != NULL);

          SgType* type = new SgTypeInt();
          ROSE_ASSERT(type != NULL);

          SgName name = "newVariable";

          SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(sourceLocation,name,type);
          ROSE_ASSERT(variableDeclaration != NULL);

          SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin());
          initializedName->set_file_info(Sg_File_Info::generateDefaultFileInfoForTransformationNode());

       // DQ (6/18/2007): The unparser requires that the scope be set (for name qualification to work).
          initializedName->set_scope(block);

       // Liao (2/13/2008): AstTests requires this to be set
          variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration);

          ROSE_ASSERT(block->get_statements().size() > 0);

          block->get_statements().insert(block->get_statements().begin(),variableDeclaration);
          variableDeclaration->set_parent(block);

       // Add a symbol to the sybol table for the new variable
          SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName);
          block->insert_symbol(name,variableSymbol);
        }
   }
Example #4
0
bool ClangToSageTranslator::VisitEnumDecl(clang::EnumDecl * enum_decl, SgNode ** node) {
#if DEBUG_VISIT_DECL
    std::cerr << "ClangToSageTranslator::VisitEnumDecl" << std::endl;
#endif
    bool res = true;

    SgName name(enum_decl->getNameAsString());


    clang::EnumDecl * prev_enum_decl = enum_decl->getPreviousDeclaration();
    SgEnumSymbol * sg_prev_enum_sym = isSgEnumSymbol(GetSymbolFromSymbolTable(prev_enum_decl));
    SgEnumDeclaration * sg_prev_enum_decl = sg_prev_enum_sym == NULL ? NULL : isSgEnumDeclaration(sg_prev_enum_sym->get_declaration());
    sg_prev_enum_decl = sg_prev_enum_decl == NULL ? NULL : isSgEnumDeclaration(sg_prev_enum_decl->get_definingDeclaration());

    SgEnumDeclaration * sg_enum_decl = SageBuilder::buildEnumDeclaration(name, SageBuilder::topScopeStack());
    *node = sg_enum_decl;

    if (sg_prev_enum_decl == NULL || sg_prev_enum_decl->get_enumerators().size() == 0) {
      clang::EnumDecl::enumerator_iterator it;
      for (it = enum_decl->enumerator_begin(); it != enum_decl->enumerator_end(); it++) {
          SgNode * tmp_enumerator = Traverse(*it);
          SgInitializedName * enumerator = isSgInitializedName(tmp_enumerator);

          ROSE_ASSERT(enumerator);

          enumerator->set_scope(SageBuilder::topScopeStack());
          sg_enum_decl->append_enumerator(enumerator);
      }
    }
    else {
      sg_enum_decl->set_definingDeclaration(sg_prev_enum_decl);
      sg_enum_decl->set_firstNondefiningDeclaration(sg_prev_enum_decl->get_firstNondefiningDeclaration());
    }

    return VisitDecl(enum_decl, node) && res;
}
void
FunctionCallNormalization::visit( SgNode *astNode )
   {
     SgStatement *stm = isSgStatement( astNode );

     // visiting all statements which may contain function calls;
     // Note 1: we do not look at the body of loops, or sequences of statements, but only
     // at statements which may contain directly function calls; all other statements will have their component parts visited in turn
     if ( isSgEnumDeclaration( astNode ) || isSgVariableDeclaration( astNode ) || isSgVariableDefinition( astNode ) ||
                               isSgExprStatement( astNode ) || isSgForStatement( astNode ) || isSgReturnStmt( astNode ) ||
                               isSgSwitchStatement( astNode ) )
        {
       // maintain the mappings from function calls to expressions (variables or dereferenced variables)
          map<SgFunctionCallExp *, SgExpression *> fct2Var;

       // list of Declaration structures, one structure per function call
          DeclarationPtrList declarations;
          bool variablesDefined = false;
             
       // list of function calls, in correnspondence with the inForTest list below
          list<SgNode*> functionCallExpList;
          list<bool> inForTest;

          SgForStatement *forStm = isSgForStatement( stm );
          SgSwitchStatement *swStm = isSgSwitchStatement( stm );
          list<SgNode*> temp1, temp2;

       // for-loops and Switch statements have conditions ( and increment ) expressed as expressions
       // and not as standalone statements; this will change in future Sage versions
       // TODO: when for-loops and switch statements have conditions expressed via SgStatements
       // these cases won't be treated separately; however, do-while will have condition expressed via expression
       // so that will be the only exceptional case to be treated separately
          if (forStm != NULL)
             {
            // create a list of function calls in the condition and increment expression
            // the order is important, the condition is evaluated after the increment expression
            // temp1 = FEOQueryForNodes( forStm->get_increment_expr_root(), V_SgFunctionCallExp );
            // temp2 = FEOQueryForNodes( forStm->get_test_expr_root(), V_SgFunctionCallExp );
               temp1 = FEOQueryForNodes( forStm->get_increment(), V_SgFunctionCallExp );
               temp2 = FEOQueryForNodes( forStm->get_test_expr(), V_SgFunctionCallExp );
               functionCallExpList = temp1;
               functionCallExpList.splice( functionCallExpList.end(), temp2 );
             }
            else
             {
               if (swStm != NULL)
                  {
                 // create a list of function calls in the condition in the order of function evaluation
                 // DQ (11/23/2005): Fixed SgSwitchStmt to have SgStatement for conditional.
                 // list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector_root(), V_SgFunctionCallExp );
                    list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector(), V_SgFunctionCallExp );
                    functionCallExpList = temp1;
                  }
                 else
                  {
                 // create a list of function calls in the statement in the order of function evaluation
                    functionCallExpList = FEOQueryForNodes( stm, V_SgFunctionCallExp );
                  }
             }

         // all function calls get replaced: this is because they can occur in expressions (e.g. for-loops)
         // which makes it difficult to build control flow graphs
         if ( functionCallExpList.size() > 0 )
           {
             cout << "--------------------------------------\nStatement ";
             cout << stm->unparseToString() << "\n";;
             
             // traverse the list of function calls in the current statement, generate a structure  Declaration for each call
             // put these structures in a list to be inserted in the code later
             for ( list<SgNode *>::iterator i = functionCallExpList.begin(); i != functionCallExpList.end(); i++ )
               {
                 variablesDefined = true;

                 // get function call exp
                 SgFunctionCallExp *exp = isSgFunctionCallExp( *i );
                 ROSE_ASSERT ( exp );
                 
                 // get type of expression, generate unique variable name
                 SgType *expType = exp->get_type();
                 ROSE_ASSERT ( expType );
                 Sg_File_Info *location = Sg_File_Info::generateDefaultFileInfoForTransformationNode();
                 ROSE_ASSERT ( location );
                 ostringstream os;
                 os << "__tempVar__" << location;
                 SgName name = os.str().c_str();

                 // replace previous variable bindings in the AST
                 SgExprListExp *paramsList = exp->get_args();
                 SgExpression *function = exp->get_function();
                 ROSE_ASSERT ( paramsList && function );
                 replaceFunctionCallsInExpression( paramsList, fct2Var );
                 replaceFunctionCallsInExpression( function, fct2Var );

                 // duplicate function call expression, for the initialization declaration and the assignment
                 SgTreeCopy treeCopy;
                 SgFunctionCallExp *newExpInit = isSgFunctionCallExp( exp->copy( treeCopy ) );
                 ROSE_ASSERT ( newExpInit );
                 SgFunctionCallExp *newExpAssign = isSgFunctionCallExp( exp->copy( treeCopy ) );
                 ROSE_ASSERT ( newExpAssign );

                 // variables
                 Sg_File_Info *initLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(),
                   *nonInitLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(),
                   *assignLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode();
                 Declaration *newDecl = new Declaration();
                 SgStatement *nonInitVarDeclaration, *initVarDeclaration, *assignStmt;
                 SgExpression *varRefExp;
                 SgVariableSymbol *varSymbol;
                 SgAssignOp *assignOp;
                 SgInitializedName *initName;

                 bool pointerTypeNeeded = false;

                 // mark whether to replace inside or outside of ForStatement due to the
                 // function call being inside the test or the increment for a for-loop statement
                 // the 'inForTest' list is in 1:1  ordered correpondence with the 'declarations' list
                 if ( forStm )
                   {
        // SgExpressionRoot
                  //   *testExp = isSgForStatement( astNode )->get_test_expr_root(),
                  //   *incrExp = isSgForStatement( astNode )->get_increment_expr_root();
                     SgExpression
                       *testExp = isSgForStatement( astNode )->get_test_expr(),
                       *incrExp = isSgForStatement( astNode )->get_increment();
                     SgNode *up = exp;
                     while ( up && up != testExp && up != incrExp )
                       up = up->get_parent();
                     ROSE_ASSERT ( up );

                     // function call is in the condition of the for-loop
                     if ( up == testExp )
                       inForTest.push_back( true );
                     // function call is in the increment expression
                     else
                       {
                         inForTest.push_back( false );

                         // for increment expressions we need to be able to reassign the return value
                         // of the function; if the ret value is a reference, we need to generate a
                         // pointer of that type (to be able to reassign it later)
                         if ( isSgReferenceType( expType ) )
                           pointerTypeNeeded = true;
                       }
                   }

                 // for do-while statements:  we need to generate declaration of type pointer to be able to have
                 // non-assigned references when looping and assign them at the end of the body of the loop
                 if ( isSgDoWhileStmt( stm->get_parent() ) && isSgReferenceType( expType ) )
                   pointerTypeNeeded = true;

                 // we have a function call returning a reference and we can't initialize the variable
                 // at the point of declaration; we need to define the variable as a pointer
                 if ( pointerTypeNeeded )
                   {
                     // create 'address of' term for function expression, so we can assign it to the pointer
                     SgAddressOfOp *addressOp = new SgAddressOfOp( assignLoc, newExpAssign, expType );

                     // create noninitialized declaration
                     SgType *base = isSgReferenceType( expType )->get_base_type();
                     ROSE_ASSERT( base );
                     SgPointerType *ptrType = SgPointerType::createType( isSgReferenceType( expType )->get_base_type() );
                     ROSE_ASSERT ( ptrType );
                     nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, ptrType );

                     // create assignment (symbol, varRefExp, assignment)
                     initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name );
                     ROSE_ASSERT ( initName );

                     varSymbol = new SgVariableSymbol( initName );
                     ROSE_ASSERT ( varSymbol );
                     varRefExp = new SgVarRefExp( assignLoc, varSymbol );

                     SgPointerDerefExp *ptrDeref= new SgPointerDerefExp( assignLoc, varRefExp, expType );
                     ROSE_ASSERT ( isSgExpression( varRefExp ) && ptrDeref );
                     assignOp = new SgAssignOp( assignLoc, varRefExp, addressOp, ptrType );
                     assignStmt = new SgExprStatement( assignLoc, assignOp );
                     ROSE_ASSERT ( assignStmt &&  nonInitVarDeclaration );
           
                     // we don't need initialized declarations in this case
                     initVarDeclaration = NULL;

                     // save new mapping
                     fct2Var.insert( Fct2Var( exp, ptrDeref ) );
                   }
                 else
                   {
                     // create (non- &)initialized declarations, initialized name & symbol
                     SgAssignInitializer *declInit = new SgAssignInitializer( initLoc, newExpInit, expType );
                     ROSE_ASSERT ( declInit );
                     initVarDeclaration = new SgVariableDeclaration ( initLoc, name, expType, declInit );
                     nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, expType );
                     ROSE_ASSERT ( initVarDeclaration && nonInitVarDeclaration );

                     initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name );
                     ROSE_ASSERT ( initName );
                     newExpInit->set_parent( initName );
                     varSymbol = new SgVariableSymbol( initName );
                     ROSE_ASSERT ( varSymbol );

                     // create variable ref exp
                     varRefExp = new SgVarRefExp( assignLoc, varSymbol );
                     ROSE_ASSERT ( isSgVarRefExp( varRefExp ) );

                     // create the assignment
                     assignOp = new SgAssignOp( assignLoc, varRefExp, newExpAssign, expType );
                     assignStmt = new SgExprStatement( assignLoc, assignOp );
                     ROSE_ASSERT ( assignStmt );

                     initVarDeclaration->set_parent( stm->get_parent() );
                     isSgVariableDeclaration( initVarDeclaration )->set_definingDeclaration( isSgDeclarationStatement( initVarDeclaration ) );

                     // save new mapping
                     fct2Var.insert( Fct2Var( exp, varRefExp ) );
                   }

                 // save the 'declaration' structure, with all 3 statements and the variable name
                 newDecl->nonInitVarDeclaration = nonInitVarDeclaration;
                 newDecl->initVarDeclaration = initVarDeclaration;
                 newDecl->assignment = assignStmt;
                 newDecl->name = name;
                 nonInitVarDeclaration->set_parent( stm->get_parent() );
                 isSgVariableDeclaration( nonInitVarDeclaration )->set_definingDeclaration( isSgVariableDeclaration( nonInitVarDeclaration ) );
                 assignStmt->set_parent( stm->get_parent() );
                 declarations.push_back( newDecl );
               } // end for
           } // end if  fct calls in crt stmt > 1

         SgScopeStatement *scope = stm->get_scope();
         ROSE_ASSERT ( scope );
         
         // insert function bindings to variables; each 'declaration' structure in the list
         // corresponds to one function call
         for ( DeclarationPtrList::iterator i = declarations.begin(); i != declarations.end(); i++ )
           {
             Declaration *d = *i;
             ROSE_ASSERT ( d && d->assignment && d->nonInitVarDeclaration );

             // if the current statement is a for-loop, we insert Declarations before & in the loop body, depending on the case
             if ( forStm )
               {
                 SgStatement *parentScope = isSgStatement( stm->get_scope() );
                 SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfFor(forStm);
                 ROSE_ASSERT ( !inForTest.empty() && body && parentScope );
                 // SgStatementPtrList &list = body->get_statements();

                 // if function call is in loop condition, we add initialized variable before the loop and at its end
                 // hoist initialized variable declarations outside the loop
                 if ( inForTest.front() )
                   {
                     ROSE_ASSERT ( d->initVarDeclaration );
                     parentScope->insert_statement( stm, d->initVarDeclaration );

                     // set the scope of the initializedName
                     SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name );
                     ROSE_ASSERT ( initName );
                     initName->set_scope( isSgScopeStatement( parentScope ) );
                     ROSE_ASSERT ( initName->get_scope() );
                   }
                 // function call is in loop post increment so add noninitialized variable decls above the loop
                 else
                   {
                     parentScope->insert_statement( stm, d->nonInitVarDeclaration );

                     // set the scope of the initializedName
                     SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name );
                     ROSE_ASSERT ( initName );
                     initName->set_scope( isSgScopeStatement( parentScope ) );
                     ROSE_ASSERT ( initName->get_scope() );
                   }

                 // in a for-loop, always insert assignments at the end of the loop
                 body->get_statements().push_back( d->assignment );
                 d->assignment->set_parent( body );

                 // remove marker
                 inForTest.pop_front();
               }
             else
               {
                 // look at the type of the enclosing scope
                 switch ( scope->variantT() )
                   {

                     // while stmts have to repeat the function calls at the end of the loop;
                     // note there is no "break" statement, since we want to also add initialized
                     // declarations before the while-loop
                   case V_SgWhileStmt:
                     {
                       // assignments need to be inserted at the end of each while loop
                       SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfWhile(isSgWhileStmt( scope ) );
                       ROSE_ASSERT ( body );
                       d->assignment->set_parent( body );
                       body->get_statements().push_back( d->assignment );
                     }

                     // SgForInitStatement has scope SgForStatement, move declarations before the for loop;
                     // same thing if the enclosing scope is an If, or Switch statement
                   case V_SgForStatement:
                   case V_SgIfStmt:
                   case V_SgSwitchStatement:
                     {
                       // adding bindings (initialized variable declarations only, not assignments)
                       // outside the statement, in the parent scope
                       SgStatement *parentScope = isSgStatement( scope->get_parent() );
                       ROSE_ASSERT ( parentScope );
                       parentScope->insert_statement( scope, d->initVarDeclaration, true );\

                       // setting the scope of the initializedName
                       SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name );
                       ROSE_ASSERT ( initName );
                       initName->set_scope( scope->get_scope() );
                       ROSE_ASSERT ( initName->get_scope() );
                     }
                     break;

                     // do-while needs noninitialized declarations before the loop, with assignments inside the loop
                   case V_SgDoWhileStmt:
                     {
                       // adding noninitialized variable declarations before the body of the loop
                       SgStatement *parentScope = isSgStatement( scope->get_parent() );
                       ROSE_ASSERT ( parentScope );
                       parentScope->insert_statement( scope, d->nonInitVarDeclaration, true );

                       // initialized name scope setting
                       SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name );
                       ROSE_ASSERT ( initName );
                       initName->set_scope( scope->get_scope() );
                       ROSE_ASSERT ( initName->get_scope() );

                       // adding assignemts at the end of the do-while loop
                       SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfDoWhile( isSgDoWhileStmt(scope) );
                       ROSE_ASSERT ( body );
                       body->get_statements().push_back( d->assignment );
                       d->assignment->set_parent(body);
                     }
                     break;

                     // for all other scopes, add bindings ( initialized declarations ) before the statement, in the same scope
                   default:
                     scope->insert_statement( stm, d->initVarDeclaration, true );

                     // initialized name scope setting
                     SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name );
                     ROSE_ASSERT ( initName );
                     initName->set_scope( scope->get_scope() );
                     ROSE_ASSERT ( initName->get_scope() );
                   }
               }
           }
         
         // once we have inserted all variable declarations, we need to replace top-level calls in the original statement
         if ( variablesDefined )
           {
             cout << "\tReplacing in the expression " << stm->unparseToString() << "\n";

             // for ForStatements, replace expressions in condition and increment expressions,
             // not in the body, since those get replace later
             if ( forStm )
               {
         // SgExpressionRoot *testExp = forStm->get_test_expr_root(), *incrExp = forStm->get_increment_expr_root();
            SgExpression *testExp = forStm->get_test_expr(), *incrExp = forStm->get_increment();
            replaceFunctionCallsInExpression( incrExp, fct2Var );
            replaceFunctionCallsInExpression( testExp, fct2Var );
               }
             else
               if ( swStm )
             {
            // DQ (11/23/2005): Fixed SgSwitch to permit use of declaration for conditional
            // replaceFunctionCallsInExpression( swStm->get_item_selector_root(), fct2Var );
               replaceFunctionCallsInExpression( swStm->get_item_selector(), fct2Var );
             }
               else
             replaceFunctionCallsInExpression( stm, fct2Var );
           }
       } // end if isSgStatement block
   }
Example #6
0
// Do partial redundancy elimination, looking for copies of one expression expr
// within the basic block root.  A control flow graph for root must be provided
// in cfg, with a map from nodes to their statements in node_statements, a map
// from edges to their CFG edge types in edge_type, and a map from edges to
// their insertion points in edge_insertion_point.  The algorithm used is that
// of Paleri, Srikant, and Shankar ("Partial redundancy elimination: a simple,
// pragmatic, and provably correct algorithm", Science of Computer Programming
// 48 (2003) 1--20).
void PRE::partialRedundancyEliminationOne( SgExpression* expr, SgBasicBlock* root, const myControlFlowGraph& cfg)
{
    // SgBasicBlock* myFunctionBody = getFunctionDefinition(expr)->get_body();

    // DQ (3/16/2006): Added assertions
    ROSE_ASSERT(expr != NULL);
    ROSE_ASSERT(root != NULL);

    vector<SgVariableSymbol*> symbols_in_expression = SageInterface::getSymbolsUsedInExpression(expr);

    if (anyOfListPotentiallyModifiedIn(symbols_in_expression, expr))
    {
        // This expression updates its own arguments, and so is not idempotent
        // Return immediately
        return;
    }

    // Simple or not user-definable expressions
    if (isSgVarRefExp(expr)) return;
    if (isSgValueExp(expr)) return;
    if (isSgFunctionRefExp(expr)) return;
    if (isSgExprListExp(expr)) return;
    if (isSgInitializer(expr)) return;
#if 0
    if ( (isSgAddOp(expr) || isSgSubtractOp(expr)) &&
            (isSgVarRefExp(isSgBinaryOp(expr)->get_lhs_operand()) ||
             isSgValueExp(isSgBinaryOp(expr)->get_lhs_operand())) &&
            (isSgVarRefExp(isSgBinaryOp(expr)->get_rhs_operand()) ||
             isSgValueExp(isSgBinaryOp(expr)->get_rhs_operand())))
        return;
#endif

    // Expressions which do not keep a consistent value each time they are used
    if (!expressionTreeEqual(expr, expr))
        return;

    // cerr << "Trying to do PRE using expression " << expr->unparseToString() << " whose type is " << expr->sage_class_name() << endl;

    VertexIter i   = cfg.graph.vertices().begin(),
               end = cfg.graph.vertices().end();

    // cerr << "CFG has " << distance(i, end) << " nodes" << endl;

    bool needToMakeCachevar = false;
    set<SgNode*> replacements;
    vector<pair<SgNode*, bool /* before */> > insertions;

    vector<bool> transp(cfg.graph.vertices().size()),
           comp(cfg.graph.vertices().size()),
           antloc(cfg.graph.vertices().size());

    vector<SgNode*> first_computation(cfg.graph.vertices().size()),
           last_computation(cfg.graph.vertices().size());

    // Set values of local node properties
    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        const vector<SgNode*>& stmts = cfg.node_statements[*i];

        // Precompute test values for each statement
        vector<bool> argumentsModifiedInStatement(stmts.size());
        vector<int> expressionComputedInStatement(stmts.size());
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            if (anyOfListPotentiallyModifiedIn(symbols_in_expression, stmts[j]))
                argumentsModifiedInStatement[j] = true;
            expressionComputedInStatement[j] = countComputationsOfExpressionIn(expr, stmts[j]);
        }

        // Compute transp
        transp[*i] = true;
        for (unsigned int j = 0; j < stmts.size(); ++j)
            if (argumentsModifiedInStatement[j])
                transp[*i] = false;

        // Compute comp and do local redundancy elimination
        comp[*i] = false;
        SgNode* firstComputationInChain = 0;
        bool needToInsertComputation = false;
        bool computationInsertedOrUsed = false;
        // cout << "In node " << *i << endl;
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            // cout << "In stmt " << j << ", expressionComputedInStatement = " << expressionComputedInStatement[j]
            //      << ", argumentsModifiedInStatement = " << argumentsModifiedInStatement[j] << endl;
            if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j] && comp[*i] /* from last iter */)
            {
                // Do local redundancy elimination
                if (firstComputationInChain && needToInsertComputation)
                {
                    insertions.push_back(make_pair(firstComputationInChain, true));
                    replacements.insert(firstComputationInChain);
                    needToInsertComputation = false;
                }
                replacements.insert(stmts[j]);
                computationInsertedOrUsed = true;
                needToMakeCachevar = true;
            }
            if (expressionComputedInStatement[j])
            {
                comp[*i] = true;
                if (!firstComputationInChain)
                {
                    firstComputationInChain = stmts[j];
                    needToInsertComputation = true;
                    if (expressionComputedInStatement[j] >= 2)
                    {
                        insertions.push_back(make_pair(stmts[j], true));
                        needToMakeCachevar = true;
                        needToInsertComputation = false;
                        computationInsertedOrUsed = true;
                        replacements.insert(stmts[j]);
                    }
                }
                last_computation[*i] = stmts[j];
            }
            if (argumentsModifiedInStatement[j])
            {
                comp[*i] = false; // Must come after expressionComputedInStatement check
                firstComputationInChain = 0;
                needToInsertComputation = false;
            }
        }

        assert (!computationInsertedOrUsed || needToMakeCachevar);

        // Compute antloc
        antloc[*i] = false;
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j])
            {
                antloc[*i] = true;
                first_computation[*i] = stmts[j];
                break;
            }
            if (argumentsModifiedInStatement[j])
            {
                antloc[*i] = false;
                break;
            }
        }
    }

// #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl;
#define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl;
    PRINT_PROPERTY(transp);
    PRINT_PROPERTY(comp);
    PRINT_PROPERTY(antloc);

    int (simpleGraph::*source_ptr)(int) const = &simpleGraph::source;
    int (simpleGraph::*target_ptr)(int) const = &simpleGraph::target;

    vector<bool> avin(cfg.graph.vertices().size(), true);
    vector<bool> avout(cfg.graph.vertices().size(), true);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(avin, cfg);
    FIXPOINT_OUTPUT_BEGIN(avout, cfg);
    avin[v] = accumulate_neighbors(cfg, v, avout,cfg.graph.in_edges(v),&simpleGraph::source, logical_and<bool>(), true, false);
    avout[v] = comp[v] || (avin[v] && transp[v]);
    FIXPOINT_OUTPUT_END(avout, <=, cfg);
    FIXPOINT_OUTPUT_END(avin, <=, cfg);
    FIXPOINT_END(cfg, out_edges, OutEdgeIter)

    PRINT_PROPERTY(avin);
    PRINT_PROPERTY(avout);

    vector<bool> antin(cfg.graph.vertices().size(), true);
    vector<bool> antout(cfg.graph.vertices().size(), true);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(antin, cfg);
    FIXPOINT_OUTPUT_BEGIN(antout, cfg);
    antout[v] = accumulate_neighbors(cfg, v, antin, cfg.graph.out_edges(v), target_ptr, logical_and<bool>(), true, false);
    antin[v] = antloc[v] || (antout[v] && transp[v]);
    FIXPOINT_OUTPUT_END(antout, <=, cfg);
    FIXPOINT_OUTPUT_END(antin, <=, cfg);
    FIXPOINT_END(cfg, in_edges, InEdgeIter)

    PRINT_PROPERTY(antin);
    PRINT_PROPERTY(antout);

    vector<bool> safein(cfg.graph.vertices().size()), safeout(cfg.graph.vertices().size());

    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        safein[*i] = avin[*i] || antin[*i];
        safeout[*i] = avout[*i] || antout[*i];
    }

    PRINT_PROPERTY(safein);
    PRINT_PROPERTY(safeout);

    vector<bool> spavin(cfg.graph.vertices().size(), false);
    vector<bool> spavout(cfg.graph.vertices().size(), false);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(spavin, cfg);
    FIXPOINT_OUTPUT_BEGIN(spavout, cfg);
    spavin[v] = safein[v] && accumulate_neighbors(cfg, v, spavout, cfg.graph.in_edges(v), source_ptr, logical_or<bool>(), false, false);
    spavout[v] = safeout[v] && (comp[v] || (spavin[v] && transp[v]));
    FIXPOINT_OUTPUT_END(spavout, >=, cfg);
    FIXPOINT_OUTPUT_END(spavin, >=, cfg);
    FIXPOINT_END(cfg, out_edges, OutEdgeIter)

    PRINT_PROPERTY(spavin);
    PRINT_PROPERTY(spavout);

    vector<bool> spantin(cfg.graph.vertices().size(), false);
    vector<bool> spantout(cfg.graph.vertices().size(), false);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(spantin, cfg);
    FIXPOINT_OUTPUT_BEGIN(spantout, cfg);
    spantout[v] = safeout[v] && accumulate_neighbors(cfg, v, spantin, cfg.graph.out_edges(v), target_ptr, logical_or<bool>(), false, false);
    spantin[v] = safein[v] && (antloc[v] || (spantout[v] && transp[v]));
    FIXPOINT_OUTPUT_END(spantout, >=, cfg);
    FIXPOINT_OUTPUT_END(spantin, >=, cfg);
    FIXPOINT_END(cfg, in_edges, InEdgeIter)

    PRINT_PROPERTY(spantin);
    PRINT_PROPERTY(spantout);
#undef PRINT_PROPERTY

    vector<bool> node_insert(cfg.graph.vertices().size());
    vector<bool> replacef(cfg.graph.vertices().size());
    vector<bool> replacel(cfg.graph.vertices().size());

    // printf ("Intermediate test 1: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        node_insert[*i] = comp[*i] && spantout[*i] && (!transp[*i] || !spavin[*i]);
        replacef[*i] = antloc[*i] && (spavin[*i] || (transp[*i] && spantout[*i]));
        replacel[*i] = comp[*i] && (spantout[*i] || (transp[*i] && spavin[*i]));

        if (node_insert[*i])
        {
            needToMakeCachevar = true;
            insertions.push_back(make_pair(last_computation[*i], true));
            // cerr << "Insert computation of " << expr->unparseToString() << " just before last computation in " << *i << endl;
        }

        if (replacef[*i])
        {
            needToMakeCachevar = true;
            replacements.insert(first_computation[*i]);
            // cerr << "Replace first computation of " << *i << endl;
        }

        if (replacel[*i])
        {
            needToMakeCachevar = true;
            replacements.insert(last_computation[*i]);
            // cerr << "Replace last computation of " << *i << endl;
        }
    }

    vector<bool> edge_insert(cfg.graph.edges().size());

    // printf ("Intermediate test 2: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    EdgeIter j = cfg.graph.edges().begin(), jend = cfg.graph.edges().end();
    for (; j != jend; ++j)
    {
        edge_insert[*j] = !spavout[cfg.graph.source(*j)] && spavin[cfg.graph.target(*j)] && spantin[cfg.graph.target(*j)];

        // printf ("edge_insert[*j] = %s \n",edge_insert[*j] ? "true" : "false");
        if (edge_insert[*j])
        {
            needToMakeCachevar = true;
            // cerr << "Insert computation of " << expr->unparseToString() << " on edge from "
            //      << cfg.graph.source(*j) << " to " << cfg.graph.target(*j) << endl;
        }
    }

    // printf ("Before final test: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    // Add cache variable if necessary
    SgVarRefExp* cachevar = 0;
    if (needToMakeCachevar)
    {
        SgName cachevarname = "cachevar__";
        cachevarname << ++SageInterface::gensym_counter;

        // printf ("Building variable name = %s \n",cachevarname.str());

        SgType* type = expr->get_type();
        if (isSgArrayType(type))
            type = new SgPointerType(isSgArrayType(type)->get_base_type());
        assert (SageInterface::isDefaultConstructible(type));
        // FIXME: assert (isAssignable(type));
        SgVariableDeclaration* decl = new SgVariableDeclaration(SgNULL_FILE, cachevarname, type, NULL);
        decl->set_definingDeclaration(decl);
        SgInitializedName* initname = decl->get_variables().back();

        // DQ (10/5/2007): Added an assertion.
        ROSE_ASSERT(initname != NULL);

        decl->addToAttachedPreprocessingInfo(
            new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,
                                  (string("// Partial redundancy elimination: ") + cachevarname.str() +
                                   " is a cache of " + expr->unparseToString()).c_str(),
                                  "Compiler-Generated in PRE", 0, 0, 0, PreprocessingInfo::before));
        SgVariableSymbol* cachevarsym = new SgVariableSymbol(initname);
        decl->set_parent(root);

        // DQ (10/5/2007): Added scope (suggested by Jeremiah).
        initname->set_scope(root);

        root->get_statements().insert(root->get_statements().begin(),decl);

        root->insert_symbol(cachevarname, cachevarsym);
        cachevar = new SgVarRefExp(SgNULL_FILE, cachevarsym);
        cachevar->set_endOfConstruct(SgNULL_FILE);
    }

    // Do expression computation replacements
    for (set<SgNode*>::iterator i = replacements.begin(); i != replacements.end(); ++i)
    {
        ReplaceExpressionWithVarrefVisitor(expr, cachevar).traverse(*i, postorder);
    }

    // Do edge insertions
    // int count = 0;
    bool failAtEndOfFunction = false;
    for (j = cfg.graph.edges().begin(); j != jend; ++j)
    {
        // printf ("Build the insertion list! count = %d \n",count++);
        if (edge_insert[*j])
        {
#if 0
            // DQ (3/13/2006): Compiler warns that "src" is unused, so I have commented it out!
            Vertex src = cfg.graph.source(*j), tgt = cfg.graph.target(*j);
            cerr << "Doing insertion between " << src << " and " << tgt << endl;
#endif
            pair<SgNode*, bool> insert_point = cfg.edge_insertion_point[*j];
            if (insert_point.first)
            {
                insertions.push_back(insert_point);
            }
            else
            {
                // DQ (3/16/2006): This is a visited when we fixup the NULL pointer to the initializer in a SgForStatment.
                cerr << "Warning: no insertion point found" << endl; //FIXME was assert
                printf ("Need to figure out what to do here! cfg.edge_insertion_point[*j] = %p \n",&(cfg.edge_insertion_point[*j]));

                failAtEndOfFunction = true;
                ROSE_ASSERT(false);
            }
        }
    }

    // Do within-node insertions
    // printf ("At start of loop: insertions.size() = %zu \n",insertions.size());
    for (vector<pair<SgNode*, bool> >::iterator i = insertions.begin(); i != insertions.end(); ++i)
    {
        SgTreeCopy tc1, tc2;
        SgVarRefExp* cachevarCopy = isSgVarRefExp(cachevar->copy(tc1));
        ROSE_ASSERT (cachevarCopy);
        cachevarCopy->set_lvalue(true);
        SgExpression* operation = new SgAssignOp(SgNULL_FILE, cachevarCopy, isSgExpression(expr->copy(tc2)));
#if 0
        printf ("Inside of loop: insertions.size() = %zu \n",insertions.size());
        printf ("\n\ni->first = %p = %s = %s \n",i->first,i->first->class_name().c_str(),i->first->unparseToString().c_str());
        printf ("operation = %p = %s = %s \n",operation,operation->class_name().c_str(),operation->unparseToString().c_str());
#endif
        if (isSgExpression(i->first) && !i->second)
        {
            SgNode* ifp = i->first->get_parent();
            SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, isSgExpression(i->first), operation);
            operation->set_parent(comma);
            comma->set_parent(ifp);
            i->first->set_parent(comma);
            if (isSgForStatement(ifp))
            {
                isSgForStatement(ifp)->set_increment(comma);
            }
            else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_lhs_operand() == i->first)
            {
                isSgBinaryOp(ifp)->set_lhs_operand(comma);
            }
            else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_rhs_operand() == i->first)
            {
                isSgBinaryOp(ifp)->set_rhs_operand(comma);
            }
            else if (isSgUnaryOp(ifp) && isSgUnaryOp(ifp)->get_operand() == i->first)
            {
                isSgUnaryOp(ifp)->set_operand(comma);
            }
            else
            {
                cerr << ifp->sage_class_name() << endl;
                assert (!"Bad parent type for inserting comma expression");
            }
        }
        else
        {
            SgStatement* the_computation = new SgExprStatement(SgNULL_FILE, operation);
            operation->set_parent(the_computation);
            // printf ("In pre.C: the_computation = %p = %s \n",the_computation,the_computation->class_name().c_str());

            if (isSgBasicBlock(i->first) && i->second)
            {
                isSgBasicBlock(i->first)->get_statements().insert(isSgBasicBlock(i->first)->get_statements().begin(),the_computation);
                the_computation->set_parent(i->first);
            }
            else
            {
#if 0
                // DQ (3/14/2006): Bug here when SgExprStatement from SgForStatement test is used here!
                printf ("Bug here when SgExprStatement from SgForStatement test is used: i->first = %s \n",i->first->class_name().c_str());
                i->first->get_file_info()->display("Location i->first");
                printf ("Bug here when SgExprStatement from SgForStatement test is used: TransformationSupport::getStatement(i->first) = %s \n",
                        TransformationSupport::getStatement(i->first)->class_name().c_str());
                printf ("Bug here when SgExprStatement from SgForStatement test is used: the_computation = %s \n",the_computation->class_name().c_str());
                the_computation->get_file_info()->display("Location the_computation: debug");
                ROSE_ASSERT(i->first != NULL);
                ROSE_ASSERT(i->first->get_parent() != NULL);
                printf ("i->first->get_parent() = %s \n",i->first->get_parent()->class_name().c_str());
                i->first->get_file_info()->display("Location i->first: debug");
#endif

                SgForStatement*  forStatement = isSgForStatement(i->first->get_parent());
                if (forStatement != NULL)
                {
                    // Make sure that both pointers are not equal because they are both NULL!
                    ROSE_ASSERT(forStatement->get_test() != NULL);
                    SgExprStatement* possibleTest = isSgExprStatement(i->first);
                    if ( forStatement->get_test() == possibleTest )
                    {
                        // This is a special case of a SgExpressionStatement as a target in a SgForStatement
                        // printf ("Found special case of target being the test of a SgForStatement \n");
                        forStatement->set_test(the_computation);
                        the_computation->set_parent(forStatement);
                    }
                }
                else
                {
                    SgForInitStatement*  forInitStatement = isSgForInitStatement(i->first->get_parent());
                    if (forInitStatement != NULL)
                    {
                        // printf ("Found the SgForInitStatement \n");
                        SgVariableDeclaration* possibleVariable = isSgVariableDeclaration(i->first);
                        SgExprStatement* possibleExpression = isSgExprStatement(i->first);
                        SgStatementPtrList & statementList = forInitStatement->get_init_stmt();
                        SgStatementPtrList::iterator i = statementList.begin();
                        bool addToForInitList = false;
                        while ( (addToForInitList == false) && (i != statementList.end()) )
                        {
                            // if ( *i == possibleVariable )
                            if ( *i == possibleVariable || *i == possibleExpression )
                            {
                                // This is a special case of a SgExpressionStatement as a target in a SgForStatement
                                // printf ("Found special case of SgForInitStatement transformation \n");
                                addToForInitList = true;
                            }
                            i++;
                        }

                        // Only modify the STL list outside of the loop over the list to avoid interator invalidation
                        if (addToForInitList == true)
                        {
                            // Add the the_computation statment to the list in the SgForInitStatement.
                            // Later if we abandon the SgForInitStatement then we would have to add it to
                            // the list of SgInitializedName objects in the SgVariableDeclaration OR modify
                            // the expression list to handle the extra expression (but I think this case in
                            // handled above).
                            // printf ("Adding the_computation to the list in the SgForInitStatement \n");
                            statementList.push_back(the_computation);
                            the_computation->set_parent(forInitStatement);
                        }
                    }
                    else
                    {
                        myStatementInsert(TransformationSupport::getStatement(i->first),the_computation,i->second,true);
                        the_computation->set_parent(TransformationSupport::getStatement(i->first));
                    }
                }
            }
        }
    }

    // DQ (3/16/2006): debugging code to force failure at inspection point
    if (failAtEndOfFunction == true)
    {
        printf ("Error: internal error detected \n");
        ROSE_ASSERT(false);
    }
}
Example #7
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;
   }
Example #8
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)
{
    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()));
                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();
    SgFunctionDefinition* fundef = fundecl->get_definition();
    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);
        // thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, new SgAssignInitializer(SgNULL_FILE, thisptr));
        thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer);
        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);

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

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

    std::cout << "Trying to inline function " << fundecl->get_name().str() << std::endl;
    SgBasicBlock* funbody_raw = fundef->get_body();
    SgInitializedNamePtrList& params = fundecl->get_args();
    SgInitializedNamePtrList::iterator i;
    SgExpressionPtrList& funargs = funcall->get_args()->get_expressions();
    SgExpressionPtrList::iterator j;
    //int ctr; // unused variable, Liao
    std::vector<SgInitializedName*> inits;
    SgTreeCopy tc;
    SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc));
    ROSE_ASSERT (function_copy);
    SgBasicBlock* funbody_copy = function_copy->get_body();


    SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall);

    renameLabels(funbody_copy, targetFunction);
    std::cout << "Original symbol count: " << funbody_raw->get_symbol_table()->size() << std::endl;
    std::cout << "Copied symbol count: " << funbody_copy->get_symbol_table()->size() << std::endl;
    // std::cout << "Original symbol count f: " << fundef->get_symbol_table()->size() << std::endl;
    // std::cout << "Copied symbol count f: " << function_copy->get_symbol_table()->size() << std::endl;
    // We don't need to keep the copied function definition now that the
    // labels in it have been moved to the target function.  Having it in the
    // memory pool confuses the AST tests.
    function_copy->set_declaration(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
    ReplaceParameterUseVisitor::paramMapType paramMap;
    for (i = params.begin(), j = funargs.begin(); i != params.end() && j != funargs.end(); ++i, ++j)
    {
        SgAssignInitializer* ai = new SgAssignInitializer(SgNULL_FILE, *j, (*i)->get_type());
        ROSE_ASSERT(ai != NULL);
        ai->set_endOfConstruct(SgNULL_FILE);
        SgName shadow_name((*i)->get_name());
        shadow_name << "__" << ++gensym_counter;
        SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE,shadow_name,(*i)->get_type(),ai);
        vardecl->set_definingDeclaration(vardecl);
        vardecl->set_endOfConstruct(SgNULL_FILE);
        vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE);

        printf ("Built new SgVariableDeclaration #2 = %p = %s initializer = %p \n",vardecl,shadow_name.str(),(*(vardecl->get_variables().begin()))->get_initializer());

        vardecl->set_parent(funbody_copy);
        SgInitializedName* init = (vardecl->get_variables()).back();
        // init->set_endOfConstruct(SgNULL_FILE);
        inits.push_back(init);
        ai->set_parent(init);
        init->set_scope(funbody_copy);
        funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + (i - params.begin()), vardecl);
        SgVariableSymbol* sym = new SgVariableSymbol(init);
        paramMap[*i] = sym;
        funbody_copy->insert_symbol(shadow_name, sym);
        sym->set_parent(funbody_copy->get_symbol_table());
    }

    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()  = %zu \n",funbody_raw->get_statements().size());
    printf ("funbody_copy->get_statements().size() = %zu \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

    // printf ("Exiting as a test after testing the symbol table \n");
    // ROSE_ASSERT(false);

    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
    // std::cout << "funbody_copy is " << funbody_copy->unparseToString() << std::endl;

    ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy);
    // std::cout << "funbody_copy 2 is " << funbody_copy->unparseToString() << std::endl;
    replaceExpressionWithStatement(funcall, &previsitor);
    // std::cout << "Inline succeeded " << funcall->get_parent()->unparseToString() << std::endl;
    return true;
}
// Do finite differencing on one expression within one context.  The expression
// must be defined and valid within the entire body of root.  The rewrite rules
// are used to simplify expressions.  When a variable var is updated from
// old_value to new_value, an expression of the form (var, (old_value,
// new_value)) is created and rewritten.  The rewrite rules may either produce
// an arbitrary expression (which will be used as-is) or one of the form (var,
// (something, value)) (which will be changed to (var = value)).
void doFiniteDifferencingOne(SgExpression* e, 
                             SgBasicBlock* root,
                             RewriteRule* rules)
   {
     SgStatementPtrList& root_stmts = root->get_statements();
     SgStatementPtrList::iterator i;
     for (i = root_stmts.begin(); i != root_stmts.end(); ++i)
        {
          if (expressionComputedIn(e, *i))
               break;
        }
     if (i == root_stmts.end())
          return; // Expression is not used within root, so quit
     vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e);
     SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter;
     SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */);
     SgInitializedName* cachevar = cachedecl->get_variables().back();
     ROSE_ASSERT (cachevar);
     root->get_statements().insert(i, cachedecl);
     cachedecl->set_parent(root);
     cachedecl->set_definingDeclaration(cachedecl);
     cachevar->set_scope(root);
     SgVariableSymbol* sym = new SgVariableSymbol(cachevar);
     root->insert_symbol(cachename, sym);
     SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym);
     vr->set_endOfConstruct(SgNULL_FILE);
     replaceCopiesOfExpression(e, vr, root);

     vector<SgExpression*> modifications_to_used_symbols;
     FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root);

     cachedecl->addToAttachedPreprocessingInfo( 
          new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + 
               cachename.str() + " is a cache of " + 
               e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before));

     if (modifications_to_used_symbols.size() == 0)
        {
          SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e);
          e->set_parent(cacheinit);
          cachevar->set_initializer(cacheinit);
          cacheinit->set_parent(cachevar);
        }
       else
        {
          for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i)
             {
               SgExpression* modstmt = modifications_to_used_symbols[i];
#ifdef FD_DEBUG
               cout << "Updating cache after " << modstmt->unparseToString() << endl;
#endif
               SgExpression* updateCache = 0;
               SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym);
               varref->set_endOfConstruct(SgNULL_FILE);
               SgTreeCopy tc;
               SgExpression* eCopy = isSgExpression(e->copy(tc));
               switch (modstmt->variantT())
                  {
                    case V_SgAssignOp:
                       {
                         SgAssignOp* assignment = isSgAssignOp(modstmt);
                         assert (assignment);
                         SgExpression* lhs = assignment->get_lhs_operand();
                         SgExpression* rhs = assignment->get_rhs_operand();
                         replaceCopiesOfExpression(lhs, rhs, eCopy);
                       }
                    break;

                    case V_SgPlusAssignOp:
                    case V_SgMinusAssignOp:
                    case V_SgAndAssignOp:
                    case V_SgIorAssignOp:
                    case V_SgMultAssignOp:
                    case V_SgDivAssignOp:
                    case V_SgModAssignOp:
                    case V_SgXorAssignOp:
                    case V_SgLshiftAssignOp:
                    case V_SgRshiftAssignOp:
                       {
                         SgBinaryOp* assignment = isSgBinaryOp(modstmt);
                         assert (assignment);
                         SgExpression* lhs = assignment->get_lhs_operand();
                         SgExpression* rhs = assignment->get_rhs_operand();
                         SgTreeCopy tc;
                         SgExpression* rhsCopy = isSgExpression(rhs->copy(tc));
                         SgExpression* newval = 0;
                         switch (modstmt->variantT())
                            {
#define DO_OP(op, nonassignment) \
                              case V_##op: { \
                                   newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \
                                   newval->set_endOfConstruct(SgNULL_FILE); \
                              } \
                              break

                              DO_OP(SgPlusAssignOp, SgAddOp);
                              DO_OP(SgMinusAssignOp, SgSubtractOp);
                              DO_OP(SgAndAssignOp, SgBitAndOp);
                              DO_OP(SgIorAssignOp, SgBitOrOp);
                              DO_OP(SgMultAssignOp, SgMultiplyOp);
                              DO_OP(SgDivAssignOp, SgDivideOp);
                              DO_OP(SgModAssignOp, SgModOp);
                              DO_OP(SgXorAssignOp, SgBitXorOp);
                              DO_OP(SgLshiftAssignOp, SgLshiftOp);
                              DO_OP(SgRshiftAssignOp, SgRshiftOp);
#undef DO_OP

                              default: break;
                            }
                         assert (newval);
                         replaceCopiesOfExpression(lhs, newval, eCopy);
                       }
                    break;

                    case V_SgPlusPlusOp:
                       {
                         SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand();
                         SgIntVal* one = new SgIntVal(SgNULL_FILE, 1);
                         one->set_endOfConstruct(SgNULL_FILE);
                         SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one);
                         add->set_endOfConstruct(SgNULL_FILE);
                         lhs->set_parent(add);
                         one->set_parent(add);
                         replaceCopiesOfExpression(lhs,add,eCopy);
                            }
                    break;

                    case V_SgMinusMinusOp:
                       {
                         SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand();
                         SgIntVal* one = new SgIntVal(SgNULL_FILE, 1);
                         one->set_endOfConstruct(SgNULL_FILE);
                         SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one);
                         sub->set_endOfConstruct(SgNULL_FILE);
                         lhs->set_parent(sub);
                         one->set_parent(sub);
                         replaceCopiesOfExpression(lhs,sub,eCopy);
                       }
                    break;

                    default:
                         cerr << modstmt->sage_class_name() << endl;
                         assert (false);
                         break;
                  }

#ifdef FD_DEBUG
            cout << "e is " << e->unparseToString() << endl;
            cout << "eCopy is " << eCopy->unparseToString() << endl;
#endif
               updateCache = doFdVariableUpdate(rules, varref, e, eCopy);
#ifdef FD_DEBUG
            cout << "updateCache is " << updateCache->unparseToString() << endl;
#endif
               if (updateCache)
                  {
                    ROSE_ASSERT(modstmt != NULL);
                    SgNode* ifp = modstmt->get_parent();
                    SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt);
                    modstmt->set_parent(comma);
                    updateCache->set_parent(comma);

                    if (ifp == NULL)
                       {
                         printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str());
                         modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug");
                       }
                    ROSE_ASSERT(ifp != NULL);
#ifdef FD_DEBUG
                 cout << "New expression is " << comma->unparseToString() << endl;
                 cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl;
#endif
                    if (isSgExpression(ifp))
                       {
                         isSgExpression(ifp)->replace_expression(modstmt, comma);
                         comma->set_parent(ifp);
                       }
                      else
                       {
                      // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!)
                      // cerr << ifp->sage_class_name() << endl;
                      // assert (!"Bad parent type for inserting comma expression");
                         SgStatement* statement = isSgStatement(ifp);
                         if (statement != NULL)
                            {
#ifdef FD_DEBUG
                              printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str());
                              SgExprStatement* expresionStatement = isSgExprStatement(statement);
                              if (expresionStatement != NULL)
                                 {
                                   SgExpression* expression = expresionStatement->get_expression();
                                   printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str());
                                 }
#endif
                              statement->replace_expression(modstmt, comma);
                              comma->set_parent(statement);
                            }
                           else
                            {
                              ROSE_ASSERT(ifp != NULL);
                              printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str());
                              ROSE_ASSERT(false);
                            }
                       }

#ifdef FD_DEBUG
                    cout << "IFP is now " << ifp->unparseToString() << endl;
#endif
                  }
             }
        }
   }
void RewriteFSM::visitSgFunctionDeclaration(SgFunctionDeclaration *FD)
{
  SgFunctionDefinition *fdef = FD->get_definition();
  if (!fdef) {
    return;
  }

  if (debugHooks) {
    std::cout << "Func decl: " << FD << " " << FD->get_name() << std::endl;
  }

  std::string modName = FD->get_name().getString();
  HtdInfoAttribute *htd = getHtdInfoAttribute(fdef);

  bool isStreamingStencil = false;
  size_t pos = 0;
  if ((pos = modName.find(StencilStreamPrefix)) != std::string::npos
      && pos == 0) {
    isStreamingStencil = true;
  }

#define hostEntryPrefix  "__HTC_HOST_ENTRY_"
  bool isHostEntry = false;
  if ((pos = modName.find(hostEntryPrefix)) != std::string::npos
      && pos == 0) {
    isHostEntry = true;
  }

  // Emit a default, unnamed thread group.
  std::string modWidth = boost::to_upper_copy(modName) + "_HTID_W";
  if (isStreamingStencil) {
    // The streaming version of a stencil must have width 0.
    htd->appendDefine(modWidth, "0");
  } else if (isHostEntry) {
    htd->appendDefine(modWidth, "1");
  } else if (htd->moduleWidth != -1) {
    htd->appendDefine(modWidth, boost::lexical_cast<std::string>(htd->moduleWidth));
  } else {
    DefaultModuleWidthAttribute *dwAttr = 
        getDefaultModuleWidthAttribute(SageInterface::getGlobalScope(fdef));
    if (dwAttr) {
      htd->appendDefine(modWidth, boost::lexical_cast<std::string>(dwAttr->width));
    } else { 
      htd->appendDefine(modWidth, "5");
    }
  }
  htd->appendModule(modName, "", modWidth);

  // For streaming stencils, ProcessStencils inserts a canned sequence,
  // so we bypass generating a normal FSM.
  if (isStreamingStencil) {
    return;
  }

  //
  // Create new case body blocks for each state.
  // The first executable statement starts the first state, and each
  // label starts a new state.
  //
  std::map<SgLabelStatement *, int> labelToState;
  std::map<int, std::string> stateToName;
  SgBasicBlock *funcBody = isSgBasicBlock(fdef->get_body());
  SgStatementPtrList &stmts = funcBody->get_statements();

  std::vector<SgStatement *>::iterator SI, SP;
  for (SI = stmts.begin(); SI != stmts.end(); ++SI) {
    if (!isSgDeclarationStatement(*SI)) {
      break;
    }
  }
  if (SI == stmts.end()) {
    return;
  }
  SP = SI;

  std::vector<SgBasicBlock *> newBlocks;
  SgBasicBlock *newbb = SageBuilder::buildBasicBlock();
  newBlocks.push_back(newbb);
  stateToName[1] = "__START";
  bool prevIsLabel = false;
  for (; SI != stmts.end(); ++SI) {
    SgStatement *stmt = *SI;
    SgLabelStatement *labstmt = isSgLabelStatement(stmt);
    if (labstmt) {
      if (!prevIsLabel) {
        newbb = SageBuilder::buildBasicBlock();
        newBlocks.push_back(newbb);
      }
      int snum = newBlocks.size();
      labelToState[labstmt] = snum;
      stateToName[snum] += "__" + labstmt->get_label().getString();
      prevIsLabel = true;
#if 1
      // TODO: these labels can carry preproc infos-- but the unparser
      // doesn't output them if the label is not actually output.
      AttachedPreprocessingInfoType *comments =
          labstmt->getAttachedPreprocessingInfo();
      if (comments && comments->size() > 0) {
        std::cerr << "DEVWARN: losing Preprocinfo on label" << std::endl;
        SageInterface::dumpPreprocInfo(labstmt);
      }
#endif
      stmt->unsetOutputInCodeGeneration();
      SageInterface::appendStatement(stmt, newbb);
    } else {
      prevIsLabel = false;
      SageInterface::appendStatement(stmt, newbb);
    }
  }
  stmts.erase(SP, stmts.end());

  // Add module name to each state name and create enum decl.
  SgEnumDeclaration *enumDecl = SageBuilder::buildEnumDeclaration("states",
    fdef);
  for (int i = 1; i <= newBlocks.size(); i++) {
    stateToName[i] = modName + stateToName[i];
    boost::to_upper(stateToName[i]);
    SgName nm(stateToName[i]);
    SgInitializedName *enumerator = SageBuilder::buildInitializedName(nm,
        SageBuilder::buildIntType(),
        SageBuilder::buildAssignInitializer(SageBuilder::buildIntVal(i)));
    enumerator->set_scope(funcBody);
    enumDecl->append_enumerator(enumerator);

    // Add the instruction to the htd info.
    htd->appendInst(nm.getString());
  }
  SageInterface::prependStatement(enumDecl, funcBody);
  if (!debugHooks) {
    enumDecl->unsetOutputInCodeGeneration();
  }

  SgGlobal *GS = SageInterface::getGlobalScope(FD);
  SgVariableDeclaration *declHtValid = 
      HtDeclMgr::buildHtlVarDecl("PR_htValid", GS);
  SgVariableDeclaration *declHtInst = 
      HtDeclMgr::buildHtlVarDecl("PR_htInst", GS);
  SgFunctionDeclaration *declHtContinue = 
      HtDeclMgr::buildHtlFuncDecl("HtContinue", GS);
  SgFunctionDeclaration *declHtAssert =
     HtDeclMgr::buildHtlFuncDecl("HtAssert", GS);

  //
  // Create the finite state machine switch statement "switch (PR_htInst)",
  // and insert guard "if (PR_htValid)".
  //
  SgBasicBlock *newSwitchBody = SageBuilder::buildBasicBlock();

  SgExpression *htInstExpr = SageBuilder::buildVarRefExp(declHtInst);
  SgSwitchStatement *newSwitch = 
      SageBuilder::buildSwitchStatement(htInstExpr, newSwitchBody);

  SgExpression *htValidExpr = SageBuilder::buildVarRefExp(declHtValid);
  SgIfStmt *newIfStmt = SageBuilder::buildIfStmt(htValidExpr,
      SageBuilder::buildBasicBlock(newSwitch), 0);
  SageInterface::appendStatement(newIfStmt, funcBody);

  int casenum = 1;
  foreach (SgBasicBlock *newCaseBody, newBlocks) {
    SgExpression *caseExpr = 
        SageBuilder::buildEnumVal_nfi(casenum, enumDecl, stateToName[casenum]);
    SgCaseOptionStmt *newCase = 
        SageBuilder::buildCaseOptionStmt(caseExpr, newCaseBody);
    SageInterface::appendStatement(newCase, newSwitchBody);
    casenum++;
  }
Example #11
0
SgVariableSymbol* 
putGlobalVariablesIntoClass (Rose_STL_Container<SgInitializedName*> & globalVariables, SgClassDeclaration* classDeclaration )
   {
  // This function iterates over the list of global variables and inserts them into the iput class definition

     SgVariableSymbol* globalClassVariableSymbol = NULL;

     for (Rose_STL_Container<SgInitializedName*>::iterator var = globalVariables.begin(); var != globalVariables.end(); var++)
        {
       // printf ("Appending global variable = %s to new globalVariableContainer \n",(*var)->get_name().str());
          SgVariableDeclaration* globalVariableDeclaration = isSgVariableDeclaration((*var)->get_parent());
          assert(globalVariableDeclaration != NULL);

       // Get the global scope from the global variable directly
          SgGlobal* globalScope = isSgGlobal(globalVariableDeclaration->get_scope());
          assert(globalScope != NULL);

          if (var == globalVariables.begin())
             {
            // This is the first time in this loop, replace the first global variable with 
            // the class declaration/definition containing all the global variables!
            // Note that initializers in the global variable declarations require modification 
            // of the preinitialization list in the class's constructor!  I am ignoring this for now!
               globalScope->replace_statement(globalVariableDeclaration,classDeclaration);

            // Build source position informaiton (marked as transformation)
               Sg_File_Info* fileInfo = Sg_File_Info::generateDefaultFileInfoForTransformationNode();
               assert(fileInfo != NULL);

            // Add the variable of the class type to the global scope!
               SgClassType* variableType = new SgClassType(classDeclaration->get_firstNondefiningDeclaration());
               assert(variableType != NULL);
               SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(fileInfo,"AMPI_globals",variableType);
               assert(variableDeclaration != NULL);

               globalScope->insert_statement(classDeclaration,variableDeclaration,false);

               assert(variableDeclaration->get_variables().empty() == false);
               SgInitializedName* variableName = *(variableDeclaration->get_variables().begin());
               assert(variableName != NULL);

            // DQ (9/8/2007): Need to set the scope of the new variable.
               variableName->set_scope(globalScope);

            // build the return value
               globalClassVariableSymbol = new SgVariableSymbol(variableName);

            // DQ (9/8/2007): Need to add the symbol to the global scope (new testing requires this).
               globalScope->insert_symbol(variableName->get_name(),globalClassVariableSymbol);
               ROSE_ASSERT(globalScope->lookup_variable_symbol(variableName->get_name()) != NULL);
             }
            else
             {
            // for all other iterations of this loop ... 
            // remove variable declaration from the global scope
               globalScope->remove_statement(globalVariableDeclaration);
             }

       // add the variable declaration to the class definition
          classDeclaration->get_definition()->append_member(globalVariableDeclaration);
        }

     return globalClassVariableSymbol;
   }