Пример #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;
   }
Пример #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);
}
Пример #3
0
// ******************************************
//              MAIN PROGRAM
// ******************************************
int
main( int argc, char * argv[] )
   {
  // Initialize and check compatibility. See rose::initialize
     ROSE_INITIALIZE;

  // Build the AST used by ROSE
     SgProject* project = frontend(argc,argv);
     assert(project != NULL);

     vector<SgType*> memberTypes;
     vector<string>  memberNames;

     string name = "a";
     for (int i = 0; i < 10; i++)
        {
          memberTypes.push_back(SgTypeInt::createType());
          name = "_" + name;
          memberNames.push_back(name);
        }

  // Build the initializer
     SgExprListExp* initializerList = new SgExprListExp(SOURCE_POSITION);
     initializerList->set_endOfConstruct(SOURCE_POSITION);
     SgAggregateInitializer* structureInitializer = new SgAggregateInitializer(SOURCE_POSITION,initializerList);
     structureInitializer->set_endOfConstruct(SOURCE_POSITION);

  // Build the data member initializers for the structure (one SgAssignInitializer for each data member)
     for (unsigned int i = 0; i < memberNames.size(); i++)
        {
       // Set initial value to "i"
          SgIntVal* value = new SgIntVal(SOURCE_POSITION,i);
          value->set_endOfConstruct(SOURCE_POSITION);
          SgAssignInitializer* memberInitializer = new SgAssignInitializer(SOURCE_POSITION,value);
          memberInitializer->set_endOfConstruct(SOURCE_POSITION);
          structureInitializer->append_initializer(memberInitializer);
          memberInitializer->set_parent(structureInitializer);
        }

  // Access the first file and add a struct with data members specified
     SgSourceFile* file = isSgSourceFile((*project)[0]);
     ROSE_ASSERT(file != NULL);
     SgVariableDeclaration* variableDeclaration = buildStructVariable(file->get_globalScope(),memberTypes,memberNames,"X","x",structureInitializer);
     file->get_globalScope()->prepend_declaration(variableDeclaration);
     variableDeclaration->set_parent(file->get_globalScope());

    AstTests::runAllTests(project);
  // Code generation phase (write out new application "rose_<input file name>")
     return backend(project);
   }
Пример #4
0
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);
        }
   }
Пример #5
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);
    }
}
Пример #6
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;
   }
Пример #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)
{
    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;
}
Пример #8
0
// 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
                  }
             }
        }
   }