Ejemplo n.º 1
0
void getSgFunctionDefinition(SgFunctionDefinition* funcDef) {
	SgFunctionDeclaration* funcDefDecl = funcDef->get_declaration();
	SgFunctionParameterList* funcParamList = funcDefDecl->get_parameterList(); 
	getSgFunctionParameterList(funcParamList);
	//might need to do more later, for now all it does is instantiate its parameters
	SgBasicBlock* f_body = funcDef->get_body();
	getSgBasicBlock(f_body);
	return;		
	
}
Ejemplo n.º 2
0
void PreAndPostOrderTraversal::preOrderVisit(SgNode* n) {

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


        SgFunctionDefinition * def = isSgFunctionDefinition(n);
        if (def != NULL) {
                cout << "Found function definition " << def->get_declaration()->get_name().getString();
                Sg_File_Info * start = def->get_startOfConstruct();
                Sg_File_Info * end = def->get_endOfConstruct();
                if(start->isCompilerGenerated()) {
                        cout << ", which is compiler-generated" << endl;
                } else {
                        cout << " in file " << start->get_raw_filename() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl;
                SgBasicBlock * body = def->get_body();
        Sg_File_Info * bodyStart = body->get_startOfConstruct();
        Sg_File_Info * bodyEnd =   body->get_endOfConstruct();
        cout << "Function body from line " << bodyStart->get_line() << ", col " << bodyStart->get_col() << " to line " << bodyEnd->get_line() << ", col " << bodyEnd->get_col() << endl; 
 }
        cout << endl;
        }
}
Ejemplo n.º 3
0
SgFunctionDeclaration * CudaOutliner::generateFunction ( SgBasicBlock* s,
                                                         const string& func_name_str,
                                                         ASTtools::VarSymSet_t& syms,
							 MintHostSymToDevInitMap_t hostToDevVars,
							 const ASTtools::VarSymSet_t& pdSyms,
                                                         const ASTtools::VarSymSet_t& psyms,
                                                         SgScopeStatement* scope)
{
  //Create a function named 'func_name_str', with a parameter list from 'syms'                                                             
  //pdSyms specifies symbols which must use pointer dereferencing if replaced during outlining,  
  //only used when -rose:outline:temp_variable is used                                                                                     
  //psyms are the symbols for OpenMP private variables, or dead variables (not live-in, not live-out)    

  ROSE_ASSERT ( s && scope);
  ROSE_ASSERT(isSgGlobal(scope));

  // step 1: perform necessary liveness and side effect analysis, if requested.     
  // ---------------------------------------------------------                                                                           
  std::set< SgInitializedName *> liveIns, liveOuts;
  // Collect read-only variables of the outlining target                                                                                
  std::set<SgInitializedName*> readOnlyVars;
  if (Outliner::temp_variable||Outliner::enable_classic)
    {
      SgStatement* firstStmt = (s->get_statements())[0];
      if (isSgForStatement(firstStmt)&& Outliner::enable_liveness)
        {
          LivenessAnalysis * liv = SageInterface::call_liveness_analysis (SageInterface::getProject());
	  SageInterface::getLiveVariables(liv, isSgForStatement(firstStmt), liveIns, liveOuts);
        }
      SageInterface::collectReadOnlyVariables(s,readOnlyVars);
      if (0)//Outliner::enable_debug)
        {
          cout<<"  INFO:Mint: CudaOutliner::generateFunction()---Found "<<readOnlyVars.size()<<" read only variables..:";
          for (std::set<SgInitializedName*>::const_iterator iter = readOnlyVars.begin();
               iter!=readOnlyVars.end(); iter++)
            cout<<" "<<(*iter)->get_name().getString()<<" ";
          cout<<endl;
          cout<<"CudaOutliner::generateFunction() -----Found "<<liveOuts.size()<<" live out variables..:";
          for (std::set<SgInitializedName*>::const_iterator iter = liveOuts.begin();
               iter!=liveOuts.end(); iter++)
            cout<<" "<<(*iter)->get_name().getString()<<" ";
          cout<<endl;
        }
    }
    //step 2. Create function skeleton, 'func'.             
    // -----------------------------------------                
  SgName func_name (func_name_str);
  SgFunctionParameterList *parameterList = buildFunctionParameterList();
  
  SgType* func_Type = SgTypeVoid::createType ();
  SgFunctionDeclaration* func = createFuncSkeleton (func_name, func_Type ,parameterList, scope);

  //adds __global__ keyword 
  func->get_functionModifier().setCudaKernel();
 
  ROSE_ASSERT (func);

  // Liao, 4/15/2009 , enforce C-bindings  for C++ outlined code 
  // enable C code to call this outlined function                                                                                
  // Only apply to C++ , pure C has trouble in recognizing extern "C"                                                    
  // Another way is to attach the function with preprocessing info:                                                     
  // #if __cplusplus                                                                                                           
  // extern "C"                                                                                                              
  // #endif                                                                                                                                
  // We don't choose it since the language linkage information is not explicit in AST                                                           
  if ( SageInterface::is_Cxx_language() || is_mixed_C_and_Cxx_language() \
       || is_mixed_Fortran_and_Cxx_language() || is_mixed_Fortran_and_C_and_Cxx_language() )
    {
      // Make function 'extern "C"'                                                                                                                                         
      func->get_declarationModifier().get_storageModifier().setExtern();
      func->set_linkage ("C");
    }

  //step 3. Create the function body                                                                                       
  // -----------------------------------------                                                                                              
  // Generate the function body by deep-copying 's'.                                                                                       
              
  SgBasicBlock* func_body = func->get_definition()->get_body();
  ROSE_ASSERT (func_body != NULL);

  // This does a copy of the statements in "s" to the function body of the outlined function.                                             
  ROSE_ASSERT(func_body->get_statements().empty() == true);

  // This calls AST copy on each statement in the SgBasicBlock, but not on the block, so the                                          
  // symbol table is setup by AST copy mechanism and it is  setup properly
  SageInterface::moveStatementsBetweenBlocks (s, func_body);

  if (Outliner::useNewFile)
    ASTtools::setSourcePositionAtRootAndAllChildrenAsTransformation(func_body);

  //step 4: variable handling, including:                                                                                                  
  // -----------------------------------------                                                                                             
  //   create parameters of the outlined functions                                                                                        
  //   add statements to unwrap the parameters if wrapping is requested
  //   add repacking statements if necessary                                                                                               
  //   replace variables to access to parameters, directly or indirectly                                                                  
  //   do not wrap parameters 
  Outliner::enable_classic = true;

  functionParameterHandling(syms, hostToDevVars, pdSyms, psyms, readOnlyVars, liveOuts, func);
  ROSE_ASSERT (func != NULL);
  
  // Retest this...  // Copied the similar fix from the rose outliner                        
  //     Liao 2/6/2013. It is essential to rebuild function type after the parameter list is finalized.
  //     The original function type was build using empty parameter list.
  SgType* stale_func_type = func->get_type();
  func->set_type(buildFunctionType(func->get_type()->get_return_type(), buildFunctionParameterTypeList(func->get_parameterList())));
  SgFunctionDeclaration* non_def_func = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration ()) ;
  ROSE_ASSERT (non_def_func != NULL);
  ROSE_ASSERT (stale_func_type == non_def_func->get_type());
  non_def_func->set_type(func->get_type());

  ROSE_ASSERT(func->get_definition()->get_body()->get_parent() == func->get_definition());

  ROSE_ASSERT(scope->lookup_function_symbol(func->get_name()));

  return func;
}  
Ejemplo n.º 4
0
void
ProcTraversal::visit(SgNode *node) {
    if (isSgFunctionDeclaration(node)) {
        SgFunctionDeclaration *decl = isSgFunctionDeclaration(node);
        if (decl->get_definition() != NULL) {
            /* collect statistics */
            //AstNumberOfNodesStatistics anons;
            //anons.traverse(decl, postorder);
            //original_ast_nodes += anons.get_numberofnodes();
            //original_ast_statements += anons.get_numberofstatements();

            /* do the real work */
            Procedure *proc = new Procedure();
            proc->procnum = procnum++;
            proc->decl = decl;
            proc->funcsym
                = isSgFunctionSymbol(decl->get_symbol_from_symbol_table());
            if (proc->funcsym == NULL)
            {
#if 0
                std::cout
                        << std::endl
                        << "*** NULL function symbol for declaration "
                        << decl->unparseToString()
                        << std::endl
                        << "symbol: "
                        << (void *) decl->get_symbol_from_symbol_table()
                        << (decl->get_symbol_from_symbol_table() != NULL ?
                            decl->get_symbol_from_symbol_table()->class_name()
                            : "")
                        << std::endl
                        << "first nondef decl: "
                        << (void *) decl->get_firstNondefiningDeclaration()
                        << " sym: "
                        << (decl->get_firstNondefiningDeclaration() != NULL ?
                            (void *) decl->get_firstNondefiningDeclaration()
                            ->get_symbol_from_symbol_table()
                            : (void *) NULL)
                        << std::endl;
#endif
                if (decl->get_firstNondefiningDeclaration() != NULL)
                {
                    proc->funcsym = isSgFunctionSymbol(decl
                                                       ->get_firstNondefiningDeclaration()
                                                       ->get_symbol_from_symbol_table());
                }
            }
            assert(proc->funcsym != NULL);
            // GB (2008-05-14): We need two parameter lists: One for the names of the
            // variables inside the function definition, which is
            // decl->get_parameterList(), and one that contains any default arguments
            // the function might have. The default arguments are supposedly
            // associated with the first nondefining declaration.
            proc->params = decl->get_parameterList();
            SgDeclarationStatement *fndstmt = decl->get_firstNondefiningDeclaration();
            SgFunctionDeclaration *fnd = isSgFunctionDeclaration(fndstmt);
            if (fnd != NULL && fnd != decl)
                proc->default_params = fnd->get_parameterList();
            else
                proc->default_params = proc->params;

            SgMemberFunctionDeclaration *mdecl
                = isSgMemberFunctionDeclaration(decl);
            if (mdecl) {
                proc->class_type = isSgClassDefinition(mdecl->get_scope());
                std::string name = proc->class_type->get_mangled_name().str();
                name += "::";
                name += decl->get_name().str();
                std::string mname = proc->class_type->get_mangled_name().str();
                mname += "::";
                mname += decl->get_mangled_name().str();
                proc->memberf_name = name;
                proc->mangled_memberf_name = mname;
                proc->name = decl->get_name().str();
                proc->mangled_name = decl->get_mangled_name().str();
                // GB (2008-05-26): Computing a single this symbol for each
                // procedure. Thus, this symbol can also be compared by pointer
                // equality (as is the case for all other symbols). While we're at it,
                // we also build a VarRefExp for this which can be used everywhere the
                // this pointer occurs.
                proc->this_type = Ir::createPointerType(
                                      proc->class_type->get_declaration()->get_type());
                proc->this_sym = Ir::createVariableSymbol("this", proc->this_type);
                proc->this_exp = Ir::createVarRefExp(proc->this_sym);
            } else {
                proc->name = decl->get_name().str();
                proc->mangled_name = decl->get_mangled_name().str();
                proc->class_type = NULL;
                proc->memberf_name = proc->mangled_memberf_name = "";
                proc->this_type = NULL;
                proc->this_sym = NULL;
                proc->this_exp = NULL;
                // GB (2008-07-01): Better resolution of calls to static functions.
                // This only makes sense for non-member functions.
                SgStorageModifier &sm =
                    (fnd != NULL ? fnd : decl)->get_declarationModifier().get_storageModifier();
                proc->isStatic = sm.isStatic();
                // Note that we query the first nondefining declaration for the
                // static modifier, but we save the file of the *defining*
                // declaration. This is because the first declaration might be in
                // some header file, but for call resolution, the actual source
                // file with the definition is relevant.
                // Trace back to the enclosing file node. The definition might be
                // included in foo.c from bar.c, in which case the Sg_File_Info
                // would refer to bar.c; but for function call resolution, foo.c is
                // the relevant file.
                SgNode *p = decl->get_parent();
                while (p != NULL && !isSgFile(p))
                    p = p->get_parent();
                proc->containingFile = isSgFile(p);
            }
            proc_map.insert(std::make_pair(proc->name, proc));
            mangled_proc_map.insert(std::make_pair(proc->mangled_name, proc));
            std::vector<SgVariableSymbol* >* arglist
                = new std::vector<SgVariableSymbol* >();
            SgVariableSymbol *this_var = NULL, *this_temp_var = NULL;
            if (mdecl
                    || decl->get_parameterList() != NULL
                    && !decl->get_parameterList()->get_args().empty()) {
                proc->arg_block
                    = new BasicBlock(node_id, INNER, proc->procnum);
                if (mdecl) {
                    // GB (2008-05-26): We now compute the this pointer right at the
                    // beginning of building the procedure.
                    // this_var = Ir::createVariableSymbol("this", this_type);
                    this_var = proc->this_sym;
                    // std::string varname
                    //   = std::string("$") + proc->name + "$this";
                    // this_temp_var = Ir::createVariableSymbol(varname, proc->this_type);
                    this_temp_var = global_this_variable_symbol;
                    ParamAssignment* paramAssignment
                        = Ir::createParamAssignment(this_var, this_temp_var);
                    proc->arg_block->statements.push_back(paramAssignment);
                    arglist->push_back(this_var);
                    if (proc->name.find('~') != std::string::npos) {
                        arglist->push_back(this_temp_var);
                    }
                }
                SgInitializedNamePtrList params
                    = proc->params->get_args();
                SgInitializedNamePtrList::const_iterator i;
#if 0
                int parnum = 0;
                for (i = params.begin(); i != params.end(); ++i) {
                    SgVariableSymbol *i_var = Ir::createVariableSymbol(*i);
                    std::stringstream varname;
                    // varname << "$" << proc->name << "$arg_" << parnum++;
                    SgVariableSymbol* var =
                        Ir::createVariableSymbol(varname.str(),(*i)->get_type());
                    proc->arg_block->statements.push_back(Ir::createParamAssignment(i_var, var));
                    arglist->push_back(i_var);
                }
#else
                // GB (2008-06-23): Trying to replace all procedure-specific argument
                // variables by a global list of argument variables. This means that at
                // this point, we do not necessarily need to build a complete list but
                // only add to the CFG's argument list if it is not long enough.
                size_t func_params = params.size();
                size_t global_args = global_argument_variable_symbols.size();
                std::stringstream varname;
                while (global_args < func_params)
                {
                    varname.str("");
                    varname << "$tmpvar$arg_" << global_args++;
                    SgVariableSymbol *var
                        = Ir::createVariableSymbol(varname.str(),
                                                   global_unknown_type);
                    program->global_map[varname.str()]
                        = std::make_pair(var, var->get_declaration());
                    global_argument_variable_symbols.push_back(var);
                }
                // now create the param assignments
                size_t j = 0;
                for (i = params.begin(); i != params.end(); ++i)
                {
                    SgVariableSymbol *i_var = Ir::createVariableSymbol(params[j]);
                    SgVariableSymbol *var = global_argument_variable_symbols[j];
                    j++;
                    proc->arg_block->statements.push_back(
                        Ir::createParamAssignment(i_var, var));
                    arglist->push_back(i_var);
                }
#if 0
                // replace the arglist allocated above by the new one; this must be
                // fixed for this pointers!
                delete arglist;
                arglist = &global_argument_variable_symbols;
#endif
#endif
            } else {
                proc->arg_block = NULL;
            }
            /* If this is a constructor, call default constructors
             * of all base classes. If base class constructors are
             * called manually, these calls will be removed later. */
            if (mdecl
                    && strcmp(mdecl->get_name().str(),
                              proc->class_type->get_declaration()->get_name().str()) == 0
                    && proc->class_type != NULL) {
                SgBaseClassPtrList::iterator base;
                for (base = proc->class_type->get_inheritances().begin();
                        base != proc->class_type->get_inheritances().end();
                        ++base) {
                    SgClassDeclaration* baseclass = (*base)->get_base_class();
                    SgVariableSymbol *lhs
                        = Ir::createVariableSymbol("$tmpvar$" + baseclass->get_name(),
                                                   baseclass->get_type());
                    program->global_map["$tmpvar$" + baseclass->get_name()]
                        = std::make_pair(lhs, lhs->get_declaration());
                    SgMemberFunctionDeclaration* fd=get_default_constructor(baseclass);
                    assert(fd);
                    SgType* basetype=baseclass->get_type();
                    assert(basetype);
                    SgConstructorInitializer *sci
                        = Ir::createConstructorInitializer(fd,basetype);
                    ArgumentAssignment* a
                        = Ir::createArgumentAssignment(lhs, sci);
                    proc->arg_block->statements.push_back(a);

                    // std::string this_called_varname
                    //   = std::string("$") + baseclass->get_name() + "$this";
                    SgVariableSymbol *this_called_var
                    // = Ir::createVariableSymbol(this_called_varname,
                    //                            baseclass->get_type());
                        = global_this_variable_symbol;
                    ReturnAssignment* this_ass
                        = Ir::createReturnAssignment(this_var, this_called_var);
                    proc->arg_block->statements.push_back(this_ass);
                }
            }
            if (mdecl && mdecl->get_CtorInitializerList() != NULL
                    && !mdecl->get_CtorInitializerList()->get_ctors().empty()) {
                SgInitializedNamePtrList cis
                    = mdecl->get_CtorInitializerList()->get_ctors();
                SgInitializedNamePtrList::const_iterator i;
                if (proc->arg_block == NULL) {
                    proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum);
                }
                for (i = cis.begin(); i != cis.end(); ++i) {
                    SgVariableSymbol* lhs = Ir::createVariableSymbol(*i);
                    SgAssignInitializer *ai
                        = isSgAssignInitializer((*i)->get_initializer());
                    SgConstructorInitializer *ci
                        = isSgConstructorInitializer((*i)->get_initializer());
                    /* TODO: other types of initializers */
                    if (ai) {
                        SgClassDeclaration *class_decl
                            = proc->class_type->get_declaration();
                        // GB (2008-05-26): We now compute the this pointer right at the
                        // beginning of building the procedure.
                        // SgVarRefExp* this_ref
                        //   = Ir::createVarRefExp("this",
                        //                         Ir::createPointerType(class_decl->get_type()));
                        SgVarRefExp* this_ref = proc->this_exp;
                        SgArrowExp* arrowExp
                            = Ir::createArrowExp(this_ref,Ir::createVarRefExp(lhs));
                        // GB (2008-03-17): We need to handle function calls in
                        // initializers. In order to be able to build an argument
                        // assignment, we need to know the function's return variable, so
                        // the expression labeler must be called on it. The expression
                        // number is irrelevant, however, as it does not appear in the
                        // return variable.
                        if (isSgFunctionCallExp(ai->get_operand_i())) {
#if 0
                            ExprLabeler el(0 /*expnum*/);
                            el.traverse(ai->get_operand_i(), preorder);
                            // expnum = el.get_expnum();
#endif
                            // GB (2008-06-25): There is now a single global return
                            // variable. This may or may not mean that we can simply ignore
                            // the code above. I don't quite understand why this labeling
                            // couldn't be done later on, and where its result was used.
                        }
                        ArgumentAssignment* argumentAssignment
                            = Ir::createArgumentAssignment(arrowExp,ai->get_operand_i());
                        proc->arg_block->statements.push_back(argumentAssignment);
                    } else if (ci) {
                        /* if this is a call to a base class's
                         * constructor, remove the call we generated
                         * before */
                        SgStatement* this_a = NULL;
                        SgClassDeclaration* cd = ci->get_class_decl();
                        std::deque<SgStatement *>::iterator i;
                        for (i = proc->arg_block->statements.begin();
                                i != proc->arg_block->statements.end();
                                ++i) {
                            ArgumentAssignment* a
                                = dynamic_cast<ArgumentAssignment *>(*i);
                            if (a && isSgConstructorInitializer(a->get_rhs())) {
                                SgConstructorInitializer* c
                                    = isSgConstructorInitializer(a->get_rhs());
                                std::string c_decl_name = c->get_class_decl()->get_name().str();
                                std::string cd_name = cd->get_name().str();
                                // if (c->get_class_decl()->get_name() == cd->get_name()) {
                                if (c_decl_name == cd_name) {
#if 0
                                    // erase the following assignment
                                    // of the this pointer as well
                                    this_a = *proc->arg_block->statements.erase(i+1);
                                    proc->arg_block->statements.erase(i);
#endif
                                    // GB (2008-03-28): That's an interesting piece of code, but
                                    // it might be very mean to iterators. At least it is hard to
                                    // see whether it is correct. So let's try it like this:
                                    // erase i; we get an iterator back, which refers to the next
                                    // element. Save that element as this_a, and then erase.
                                    std::deque<SgStatement *>::iterator this_pos;
                                    this_pos = proc->arg_block->statements.erase(i);
                                    this_a = *this_pos;
                                    proc->arg_block->statements.erase(this_pos);
                                    // Good. Looks like this fixed a very obscure bug.
                                    break;
                                }
                            }
                        }
                        /* now add the initialization */
                        proc->arg_block->statements.push_back(Ir::createArgumentAssignment(lhs, ci));
                        if (this_a != NULL)
                            proc->arg_block->statements.push_back(this_a);
                    }
                }
            }
            proc->entry = new CallBlock(node_id++, START, proc->procnum,
                                        new std::vector<SgVariableSymbol *>(*arglist),
                                        (proc->memberf_name != ""
                                         ? proc->memberf_name
                                         : proc->name));
            proc->exit = new CallBlock(node_id++, END, proc->procnum,
                                       new std::vector<SgVariableSymbol *>(*arglist),
                                       (proc->memberf_name != ""
                                        ? proc->memberf_name
                                        : proc->name));
            proc->entry->partner = proc->exit;
            proc->exit->partner = proc->entry;
            proc->entry->call_target = Ir::createFunctionRefExp(proc->funcsym);
            proc->exit->call_target = Ir::createFunctionRefExp(proc->funcsym);
            /* In constructors, insert an assignment $A$this = this
             * at the end to make sure that the 'this' pointer can be
             * passed back to the calling function uncobbled. */
            proc->this_assignment = NULL;
            if (mdecl) {
                SgMemberFunctionDeclaration* cmdecl
                    = isSgMemberFunctionDeclaration(mdecl->get_firstNondefiningDeclaration());
                // if (cmdecl && cmdecl->get_specialFunctionModifier().isConstructor()) {
                proc->this_assignment
                    = new BasicBlock(node_id++, INNER, proc->procnum);
                ReturnAssignment* returnAssignment
                    = Ir::createReturnAssignment(this_temp_var, this_var);
                proc->this_assignment->statements.push_back(returnAssignment);
                add_link(proc->this_assignment, proc->exit, NORMAL_EDGE);
                // }
            }
            std::stringstream varname;
            // varname << "$" << proc->name << "$return";
            // proc->returnvar = Ir::createVariableSymbol(varname.str(),
            //                                            decl->get_type()->get_return_type());
            proc->returnvar = global_return_variable_symbol;
            procedures->push_back(proc);
            if(getPrintCollectedFunctionNames()) {
                std::cout << (proc->memberf_name != ""
                              ? proc->memberf_name
                              : proc->name)
                          << " " /*<< proc->decl << std::endl*/;
            }
            if (proc->arg_block != NULL)
            {
                proc->arg_block->call_target
                    = Ir::createFunctionRefExp(proc->funcsym);
            }
            // delete arglist;
        }
    }
}
Ejemplo n.º 5
0
void testOneFunction( std::string funcParamName,
		      vector<string> argvList,
		      bool debug, int nrOfNodes,
		      multimap <int, vector<string> >  resultsIn,
		      multimap <int, vector<string> > resultsOut) {
  cout << " \n\n------------------------------------------\nrunning (variable)... " << argvList[1] << endl;

  // Build the AST used by ROSE
  SgProject* project = frontend(argvList);
  // Call the Def-Use Analysis
  DFAnalysis* defuse = new DefUseAnalysis(project);
  int val = defuse->run(debug);
  if (debug)
    std::cerr << ">Analysis run is : " << (val ?  "failure" : "success" ) << " " << val << std::endl;
  if (val==1) exit(1);

  if (debug==false)
    defuse->dfaToDOT();


  LivenessAnalysis* liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);

  std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
  NodeQuerySynthesizedAttributeType vars = NodeQuery::querySubTree(project, V_SgFunctionDefinition);
  NodeQuerySynthesizedAttributeType::const_iterator i = vars.begin();
  bool abortme=false;
  int hitIn=0;
  int hitOut=0;
  for (; i!=vars.end();++i) {
    SgFunctionDefinition* func = isSgFunctionDefinition(*i);
    std::string name = func->class_name();
    string funcName = func->get_declaration()->get_qualified_name().str();
    if (debug)
      cerr << " .. running live analysis for func : " << funcName << endl;
    FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
    if (abortme)
      break;
    if (funcName!=funcParamName) {
      if (debug)
        cerr << "    .. skipping live analysis check for func : " << funcName << endl;
      continue;
    }
    if (rem_source.getNode()!=NULL)
      dfaFunctions.push_back(rem_source);

    NodeQuerySynthesizedAttributeType nodes = NodeQuery::querySubTree(func, V_SgNode);

    // Edg3 mistakenly adds SgType nodes to the AST; Edg4 adds some also, but fewer.  So we just remove them all. They
    // make no difference in the variable-liveness analysis anyway.
    nodes.erase(std::remove_if(nodes.begin(), nodes.end(), is_type_node), nodes.end());

    SgFunctionDeclaration* decl = isSgFunctionDeclaration(func->get_declaration());
    ROSE_ASSERT(decl);
    Rose_STL_Container<SgInitializedName*> args = decl->get_parameterList()->get_args();
    if (debug)
      cerr <<"Found args : " << args.size() << endl;
    Rose_STL_Container<SgInitializedName*>::const_iterator it = args.begin();
    for (;it!=args.end();++it) {
      nodes.push_back(*it);
    }
    if((int)nodes.size()-1!=nrOfNodes) {
      cerr << "Error :: Number of nodes = " << nodes.size()-1 << "  should be : " << nrOfNodes << endl;
      exit(1);
    } else {
      if (debug)
    	cerr << "Investigating nodes : " << nodes.size() << endl;
    }
    NodeQuerySynthesizedAttributeType::const_iterator nodesIt = nodes.begin();
    for (; nodesIt!=nodes.end();++nodesIt) {
      SgNode* node = *nodesIt;
      ROSE_ASSERT(node);
      int tableNr = defuse->getIntForSgNode(node);
      std::vector<SgInitializedName*> in = liv->getIn(node);
      std::vector<SgInitializedName*> out = liv->getOut(node);

      std::vector<string> inName;
      std::vector<string> outName;
      std::vector<SgInitializedName*>::const_iterator itv = in.begin();
      for (;itv!=in.end();++itv) {
	SgInitializedName* init = *itv;
	string name = init->get_name();
	inName.push_back(name);
      }
      itv = out.begin();
      for (;itv!=out.end();++itv) {
	SgInitializedName* init = *itv;
	string name = init->get_name();
	outName.push_back(name);
      }
      std::sort(inName.begin(), inName.end());
      std::sort(outName.begin(), outName.end());

      multimap <int, vector<string> >::const_iterator k =resultsIn.begin();
      for (;k!=resultsIn.end();++k) {
	int resNr = k->first;
	vector<string> results = k->second;
	if (debug)
      	  cerr << "   ... containing nodes : " << results.size() << " node: " << node->class_name()
               << "   tableNr : " << tableNr
               << "  resNr : " << resNr << endl;
	if (tableNr==resNr) {
	  std::sort(results.begin(), results.end());
	  if (results==inName) {
	    if (debug)
	      cerr <<"Contents in IN vector is correct! " << endl;
	  } else {
	    if (debug) {
	      cerr << " >>>>>>>>>> Problem with contents for IN ! " << endl;
	      cerr << " >>>>>>>>>> RESULT ... " << endl;
	    }
	    std::vector<string>::const_iterator itv = inName.begin();
	    for (;itv!=inName.end();++itv) {
	      string name = *itv;
	      if (debug)		cerr << name << " " ;
	    }
	    if (debug) {
	      cerr << endl;
	      cerr << " >>>>>>>>>> USER ... " << endl;
	    }
	    itv = results.begin();
	    for (;itv!=results.end();++itv) {
	      string name = *itv;
	      if (debug)	cerr << name << " " ;
	    }
	    if (debug) {
	      cerr << endl;
	    }
	    exit(1);
	  }
	  if (results.size()==in.size()) {
	    hitIn++;
	  }
	  if (debug)
	    cout << " nodeNr: " << tableNr << ".  ResultSize IN should be:" << results.size()
                 << " -  resultSize is: " << in.size()
                 << "  foundMatches == : " << hitIn << "/" << resultsIn.size() << endl;
        }
      }
      k =resultsOut.begin();
      for (;k!=resultsOut.end();++k) {
	int resNr = k->first;
	vector<string> results = k->second;
	//    	  cerr << "   ... containing nodes : " << results.size() << "   tableNr : " << tableNr <<
	//			  "  resNr : " << resNr << endl;
	if (tableNr==resNr) {
	  std::sort(results.begin(), results.end());
	  if (results==outName) {
	    if (debug)
	      cerr <<"Contents in OUT vector is correct! " << endl;
	  } 	     else {
	    if (debug) {
	      cerr << " >>>>>>>>>> Problem with contents for OUT ! " << endl;
	      cerr << " >>>>>>>>>> RESULT ... " << endl;
	    }
	    std::vector<string>::const_iterator itv = outName.begin();
	    for (;itv!=outName.end();++itv) {
	      string name = *itv;
	      if (debug)		cerr << name << " " ;
	    }
	    if (debug) {
	      cerr << endl;
	      cerr << " >>>>>>>>>> USER ... " << endl;
	    }
	    itv = results.begin();
	    for (;itv!=results.end();++itv) {
	      string name = *itv;
	      if (debug)					
		cerr << name << " " ;
	    }
	    if (debug)
	      cerr << endl;
	    exit(1);
	  }

	  if (results.size()==out.size()) {
	    hitOut++;
	  }
	  if (debug)
	    cout << " nodeNr: " << tableNr << ".  ResultSize OUT should be:" << results.size()
                 << " -  resultSize is: " << out.size()
                 << "  foundMatches == : " << hitOut << "/" << resultsOut.size() << endl;
        }
      }
      if (hitIn==0 && hitOut==0) {
	if (debug)
	  cout << " nodeNr: " << tableNr << " IN: " << hitIn << "/" << resultsIn.size() <<
	    "        Out:" << hitOut << "/" << resultsOut.size() << endl;
      }
    }
    if (hitIn!=(int)resultsIn.size() || hitOut!=(int)resultsOut.size()) {
      cout << " Error: No hit! ... DFA values of node " << nrOfNodes << " are not correct! " << endl;
      exit(1);
    }

  }
  if (debug)
    cerr << "Writing out to var.dot... " << endl;
  std::ofstream f2("var.dot");
  dfaToDot(f2, string("var"), dfaFunctions,
           (DefUseAnalysis*)defuse, liv);
  f2.close();

  if (abortme) {
    cerr<<"ABORTING ." << endl;
    ROSE_ASSERT(false);
    //    exit(1);
  }

  // iterate again and write second var.dot file
  i = vars.begin();
  abortme=false;
  std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions2;
  for (; i!=vars.end();++i) {
    SgFunctionDefinition* func = isSgFunctionDefinition(*i);
    std::string name = func->class_name();
    string funcName = func->get_declaration()->get_qualified_name().str();
    if (debug)
      cerr << " .. running live analysis for func (fixupStatementsINOUT): " << funcName << endl;
    FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
    liv->fixupStatementsINOUT(func);
    if (rem_source.getNode()!=NULL)
      dfaFunctions2.push_back(rem_source);

  }
  if (debug)
    cerr << "Writing out to varFix.dot... " << endl;
  std::ofstream f3("varFix.dot");
  dfaToDot(f3, string("varFix"), dfaFunctions2,
           (DefUseAnalysis*)defuse, liv);
  f3.close();

  if (debug)
    std::cout << "Analysis test is success." << std::endl;
}
Ejemplo n.º 6
0
SgFunctionSymbol*
SimpleInstrumentation::buildNewFunctionDeclaration ( SgStatement* statementLocation, SgFunctionType* previousFunctionType )
   {
  // *****************************************************
  // Create the functionDeclaration
  // *****************************************************

  // Must mark the newly built node to be a part of a transformation so that it will be unparsed!
     Sg_File_Info * file_info = new Sg_File_Info();
     ROSE_ASSERT(file_info != NULL);
     file_info->set_isPartOfTransformation(true);

     SgName function_name = "contest_call";
     ROSE_ASSERT(previousFunctionType != NULL);
     SgFunctionDeclaration* functionDeclaration = new SgFunctionDeclaration(file_info, function_name, previousFunctionType);
     ROSE_ASSERT(functionDeclaration != NULL);
     ROSE_ASSERT(functionDeclaration->get_parameterList() != NULL);

  // ********************************************************************
  // Create the InitializedName for a parameter within the parameter list
  // ********************************************************************
     SgTypePtrList & argList = previousFunctionType->get_arguments();
     SgTypePtrList::iterator i = argList.begin();
     while ( i != argList.end() )
        {
          SgName var_name = "";
          SgInitializer* var_initializer = NULL;
          SgInitializedName *var_init_name = new SgInitializedName(var_name, *i, var_initializer, NULL);
          functionDeclaration->get_parameterList()->append_arg(var_init_name);
          i++;
        }

  // Add any additional function arguments here! Make sure that the function type is consistant.

  // Get the scope
     SgScopeStatement* scope = statementLocation->get_scope();

  // Set the parent node in the AST (this could be done by the AstPostProcessing
     functionDeclaration->set_parent(scope);

  // Set the scope explicitly (since it could be different from the parent?)
     functionDeclaration->set_scope(scope);

  // If it is not a forward declaration then the unparser will skip the ";" at the end (need to fix this better)
     functionDeclaration->setForward();
     ROSE_ASSERT(functionDeclaration->isForward() == true);

  // Mark function as extern "C"
     functionDeclaration->get_declarationModifier().get_storageModifier().setExtern();
     functionDeclaration->set_linkage("C");  // This mechanism could be improved!

     bool inFront = true;
     SgGlobal* globalScope = TransformationSupport::getGlobalScope(statementLocation);
     SgFunctionDeclaration* functionDeclarationInGlobalScope = 
          TransformationSupport::getFunctionDeclaration(statementLocation);
     ROSE_ASSERT(globalScope != NULL);
     ROSE_ASSERT(functionDeclarationInGlobalScope != NULL);
     globalScope->insert_statement(functionDeclarationInGlobalScope,functionDeclaration,inFront);

     SgFunctionSymbol* functionSymbol = new SgFunctionSymbol(functionDeclaration);
     ROSE_ASSERT(functionSymbol != NULL);
     ROSE_ASSERT(functionSymbol->get_type() != NULL);

     return functionSymbol;
   }