// given a function call, sets argParamMap to map all simple arguments to this function to their // corresponding parameters void FunctionState::setArgParamMap(SgFunctionCallExp* call, map<varID, varID>& argParamMap) { Function func(call); SgExpressionPtrList args = call->get_args()->get_expressions(); //SgInitializedNamePtrList params = funcArgToParamByRef(call); SgInitializedNamePtrList params = func.get_params(); ROSE_ASSERT(args.size() == params.size()); //cout << "setArgParamMap() #args="<<args.size()<<" #params="<<params.size()<<"\n"; // the state of the callee's variables at the call site SgExpressionPtrList::iterator itA; SgInitializedNamePtrList::iterator itP; for(itA = args.begin(), itP = params.begin(); itA!=args.end() && itP!=params.end(); itA++, itP++) { //cout << " itA="<<(*itA)->unparseToString()<<" itP="<<(*itP)->unparseToString()<<" isValid="<<varID::isValidVarExp(*itA)<<"\n"; /*if(varID::isValidVarExp(*itA)) { varID arg(*itA); varID param(*itP); argParamMap[arg] = param; }*/ varID arg = SgExpr2Var(*itA); varID param(*itP); argParamMap[arg] = param; } }
//----------------------------------------------------------------------------------- // void Unparse_MOD_SAGE::isUnaryAddressOperator // // Auxiliary function to test if this expression is an unary operator& overloading // function //----------------------------------------------------------------------------------- bool Unparse_MOD_SAGE::isUnaryAddressOperator(SgExpression* expr) { // DQ (5/6/2007): This might be a non-member function and if so we don't handle this case correctly! // If it is a non-member function this it will have a single argument // ROSE_ASSERT(isSgFunctionRefExp(expr) == NULL); ROSE_ASSERT(expr != NULL); SgMemberFunctionRefExp* mfunc_ref = isSgMemberFunctionRefExp(expr); if (mfunc_ref != NULL) { SgMemberFunctionSymbol* mfunc_sym = mfunc_ref->get_symbol(); if (mfunc_sym != NULL) { SgMemberFunctionDeclaration* mfunc_decl = mfunc_sym->get_declaration(); if (mfunc_decl != NULL) { SgName func_name = mfunc_decl->get_name(); #if 0 printf ("In isUnaryAddressOperator(): member function: func_name = %s \n",func_name.str()); #endif if (func_name.getString() == "operator&") { SgInitializedNamePtrList argList = mfunc_decl->get_args(); if (argList.size() == 0) return true; } } } } // DQ (2/1/2018): Added to catch case of non-member function unary operator else { SgFunctionRefExp* func_ref = isSgFunctionRefExp(expr); if (func_ref != NULL) { SgFunctionSymbol* func_sym = func_ref->get_symbol(); if (func_sym != NULL) { SgFunctionDeclaration* func_decl = func_sym->get_declaration(); if (func_decl != NULL) { SgName func_name = func_decl->get_name(); #if 0 printf ("In isUnaryAddressOperator(): non-member function: func_name = %s \n",func_name.str()); #endif if (func_name.getString() == "operator&") { SgInitializedNamePtrList argList = func_decl->get_args(); if (argList.size() == 1) return true; } } } } } return false; }
virtual void visit(SgNode* n) { if (isSgInitializedName(n)) { // DQ (9/25/2007): Moved to use of std::vector instead of std::list uniformally in ROSE // ls.push_front(isSgInitializedName(n)); ls.insert(ls.begin(),isSgInitializedName(n)); } }
NameQuerySynthesizedAttributeType NameQuery::queryNameUnionFieldNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; // SgNode *sageReturnNode = NULL; SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode); if (sageClassDefinition != NULL) { ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL); if (sageClassDefinition->get_declaration ()->get_class_type () == SgClassDeclaration::e_struct) { SgDeclarationStatementPtrList declarationStatementPtrList = sageClassDefinition->get_members (); typedef SgDeclarationStatementPtrList::iterator LI; for (LI i = declarationStatementPtrList.begin (); i != declarationStatementPtrList.end (); ++i) { SgNode *listElement = *i; SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (listElement); if (sageVariableDeclaration != NULL) { typedef SgInitializedNamePtrList::iterator INITLI; SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); for (INITLI i = sageInitializedNameList.begin (); i != sageInitializedNameList.end (); ++i) { SgInitializedName* initializedListElement = *i; ROSE_ASSERT (isSgInitializedName (initializedListElement) != NULL); returnNameList.push_back (initializedListElement->get_name().str()); } /* End iteration over declarationStatementPtrList */ } /* End iteration over declarationStatementPtrList */ } } } return returnNameList; } /* End function queryUnionFieldNames() */
NodeQuerySynthesizedAttributeType NodeQuery::querySolverVariableDeclarations (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NodeQuerySynthesizedAttributeType returnNodeList; switch (astNode->variantT ()) { case V_SgVariableDeclaration: returnNodeList.push_back (astNode); break; case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: { SgFunctionDeclaration * sageFunctionDeclaration = isSgFunctionDeclaration (astNode); ROSE_ASSERT (sageFunctionDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageFunctionDeclaration->get_args (); typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; //SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration((elmVar.get_declaration())->copy()); //ROSE_ASSERT(sageVariableDeclaration != NULL); //if( sageVariableDeclaration != NULL) //AS (9/26/03) I must put an object of type const SgDeclarationStatement into the list because // I have no other way of finding the SgVariableDeclaration in the arguments. This is safe // because arguments are Variable Declarations, but puts unwelcome limits on use of returned // list because of it's constantness. ROSE_ASSERT (elmVar != NULL); returnNodeList.push_back (elmVar->get_declaration ()); //returnNodeList.push_back (sageVariableDeclaration); } break; } default: { // DQ (8/20/2005): Added default to avoid compiler warnings about unrepresented cases } } /* End switch-case */ return returnNodeList; } /* End function querySolverVariableDeclarations() */
void getSgFunctionParameterList(SgFunctionParameterList* funcParamList) { SgInitializedNamePtrList pList = funcParamList->get_args(); std::string paramReturnString; for (SgInitializedNamePtrList::iterator i = pList.begin(); i != pList.end(); i++) { std::string param = getSgInitializedName(*i); paramReturnString = paramReturnString + "\n" + param; } variables.push_back(paramReturnString); return; }
int main(int argc, char** argv) { SgProject* proj = frontend(argc,argv); SgFunctionDeclaration* mainDecl = SageInterface::findMain(proj); SgFunctionDefinition* mainDef = mainDecl->get_definition(); std::vector<SgNode*> ifExps; ifExps = NodeQuery::querySubTree(mainDef, V_SgIfStmt); for (int i = 0; i < ifExps.size(); i++) { getIfConds(isSgIfStmt(ifExps[i]), isSgScopeStatement(mainDef)); } std::vector<SgNode*> assignNodes = NodeQuery::querySubTree(mainDef, V_SgVariableDeclaration); std::cout << assignNodes.size() << " nodes found" << std::endl; std::vector<SgBinaryOp*> bin_ops; std::vector<SgUnaryOp*> un_ops; std::vector<SgNode*> other; std::vector<SgExpression*> results; for (std::vector<SgNode*>::iterator i = assignNodes.begin(); i != assignNodes.end(); i++) { SgVariableDeclaration* vdecl = isSgVariableDeclaration(*i); SgInitializedNamePtrList vlst = vdecl->get_variables(); SgInitializedName* initName = isSgInitializedName((*(vlst.begin()))); SgExpression* exp = isSgAssignInitializer(initName->get_initializer())->get_operand(); std::cout << exp->class_name() << std::endl; if (!isSgFunctionCallExp(exp)) { getExps(exp, isSgInitializedName(*i), results, 0); std::cout << "prefixes" << std::endl; for (int j = 0; j < prefixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(prefixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,true); std::cout << prefixes[j]->class_name() << std::endl; } std::cout << "results" << std::endl; for (int j = 0; j < results.size(); j++) { std::cout << results[j]->class_name() << std::endl; } std::cout << "postfixes" << std::endl; for (int j = 0; j < postfixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(postfixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,false); std::cout << postfixes[j]->class_name() << std::endl; } replaceExps(exp,vdecl); simplifyExps(exp); } } backend(proj); return 0; }
DefUseVarsInfo getDefUseVarsInfoVariableDeclaration(SgVariableDeclaration* sgn, VariableIdMapping& vidm) { SgInitializedNamePtrList variables = sgn->get_variables(); DefUseVarsInfo duvi, tduvi; SgInitializedNamePtrList::const_iterator it = variables.begin(); for( ; it != variables.end(); ++it) { tduvi = getDefUseVarsInfo_rec(*it, vidm, false); duvi = duvi + tduvi; } return duvi; }
/*! * \author Markus Schordan * \date 2012. */ VariableIdMapping::VariableIdSet VariableIdMapping::determineVariableIdsOfSgInitializedNames(SgInitializedNamePtrList& namePtrList) { VariableIdMapping::VariableIdSet resultSet; for(SgInitializedNamePtrList::iterator i=namePtrList.begin();i!=namePtrList.end();++i) { assert(*i); SgSymbol* sym=SgNodeHelper::getSymbolOfInitializedName(*i); if(sym) { resultSet.insert(variableId(sym)); } } return resultSet; }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::IntervalTransferFunctions::transferFunctionEntry(Label lab, SgFunctionDefinition* funDef,SgInitializedNamePtrList& formalParameters, Lattice& element) { // generate Intervals for each parameter variable for(SgInitializedNamePtrList::iterator i=formalParameters.begin(); i!=formalParameters.end(); ++i) { SgInitializedName* formalParameterName=*i; VariableId formalParameterVarId=_variableIdMapping->variableId(formalParameterName); IntervalPropertyState* ips=dynamic_cast<IntervalPropertyState*>(&element); ips->addVariable(formalParameterVarId); } }
string Function::str(string indent) const { ostringstream oss; oss << get_name().getString()<<"("; SgInitializedNamePtrList params = get_params(); for(SgInitializedNamePtrList::iterator in=params.begin(); in!=params.end(); ) { oss << (*in)->get_name().getString(); in++; if(in!=params.end()) oss << ", "; } oss << ")"; return oss.str(); }
/* * Discover this function's kernel interface, including I/O and functions * needed. */ void FunctionInterface::analyze() { string msg = "Analyzing function " + NAME(function); DEBUG(TOOL, msg); status = IN_PROGRESS; //Add inputs to our list SgInitializedNamePtrList inputs = function->get_parameterList()->get_args(); SgInitializedNamePtrList::const_iterator inputIt; for(inputIt = inputs.begin(); inputIt != inputs.end(); inputIt++) { msg = "\tfound input " + NAME(*inputIt); DEBUG(TOOL, msg); addInput(*inputIt); FunctionTraversal::checkVariableType((*inputIt)->get_type(), this); } //Add return value to our list (denoted by special marker name "__retval__") SgType* returnType = function->get_orig_return_type(); if(!isSgTypeVoid(returnType)) { msg = "\tfound output of type " + get_name(returnType); DEBUG(TOOL, msg); SgInitializedName* returnVal = buildInitializedName(RETVAL_NAME, returnType); addOutput(returnVal); FunctionTraversal::checkVariableType(returnType, this); } //Traverse function FunctionTraversal ft(this); ft.traverse(function, preorder); //Incorporate sub-calls //TODO do side-effect checking here for sub-calls? set<FunctionInterface*>::const_iterator funcIt; for(funcIt = calledFunctions.begin(); funcIt != calledFunctions.end(); funcIt++) { if((*funcIt)->getStatus() == NOT_ANALYZED) (*funcIt)->analyze(); combineGlobalInputs((*funcIt)->getGlobalInputs()); combineGlobalOutputs((*funcIt)->getGlobalOutputs()); combineCalledFunctions((*funcIt)->getCalledFunctions()); } status = ANALYZED; }
//----------------------------------------------------------------------------------- // void Unparse_MOD_SAGE::isUnaryOperatorPlus // // Auxiliary function to test if this expression is an unary operator+ overloading // function //----------------------------------------------------------------------------------- bool Unparse_MOD_SAGE::isUnaryOperatorPlus(SgExpression* expr) { SgMemberFunctionRefExp* mfunc_ref = isSgMemberFunctionRefExp(expr); if (mfunc_ref != NULL) { SgMemberFunctionSymbol* mfunc_sym = mfunc_ref->get_symbol(); if (mfunc_sym != NULL) { SgMemberFunctionDeclaration* mfunc_decl = mfunc_sym->get_declaration(); if (mfunc_decl != NULL) { SgName func_name = mfunc_decl->get_name(); if (func_name.getString() == "operator+") { SgInitializedNamePtrList argList = mfunc_decl->get_args(); if (argList.size() == 0) return true; } } } } // DQ (5/6/2007): Added to catch case of non-member function unary operator else { SgFunctionRefExp* func_ref = isSgFunctionRefExp(expr); if (func_ref != NULL) { SgFunctionSymbol* func_sym = func_ref->get_symbol(); if (func_sym != NULL) { SgFunctionDeclaration* func_decl = func_sym->get_declaration(); if (func_decl != NULL) { SgName func_name = func_decl->get_name(); if (func_name.getString() == "operator+") { SgInitializedNamePtrList argList = func_decl->get_args(); if (argList.size() == 1) return true; } } } } } return false; }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::LVTransferFunctions::transferFunctionEntry(Label lab, SgFunctionDefinition* funDef,SgInitializedNamePtrList& formalParameters, Lattice& element0) { LVLattice* element1=dynamic_cast<LVLattice*>(&element0); ROSE_ASSERT(element1); LVLattice& element=*element1; // remove LVs for each parameter variable for(SgInitializedNamePtrList::iterator i=formalParameters.begin(); i!=formalParameters.end(); ++i) { SgInitializedName* formalParameterName=*i; assert(formalParameterName); VariableId formalParameterVarId=_variableIdMapping->variableId(formalParameterName); element.removeVariableId(formalParameterVarId); } }
// given a function call, sets argParamMap to map all the parameters of this function to their // corresponding simple arguments, if those arguments are passed by reference void FunctionState::setParamArgByRefMap(SgFunctionCallExp* call, map<varID, varID>& paramArgByRefMap) { Function func(call); SgExpressionPtrList args = call->get_args()->get_expressions(); SgInitializedNamePtrList params = func.get_params(); SgExpressionPtrList::iterator itArgs; SgInitializedNamePtrList::iterator itParams; //cout << " #params="<<params.size()<<" #args="<<args.size()<<"\n"; for(itParams = params.begin(), itArgs = args.begin(); itParams!=params.end() && itArgs!=args.end(); itParams++, itArgs++) { /*SgType* typeParam = (*itParams)->get_type(); SgType* typeArg = cfgUtils::unwrapCasts((*itArgs))->get_type();*/ /*printf("FunctionState::setParamArgByRefMap() *itArgs=<%s | %s> isValidVar=%d\n", (*itArgs)->unparseToString().c_str(), (*itArgs)->class_name().c_str(), varID::isValidVarExp(*itArgs)); printf(" typeArg=<%s | %s>\n", typeArg->unparseToString().c_str(), typeArg->class_name().c_str()); printf(" itParams=<%s | %s>\n", (*itParams)->unparseToString().c_str(), (*itParams)->class_name().c_str()); printf(" typeParam=<%s | %s> isReference=%d\n", typeParam->unparseToString().c_str(), typeParam->class_name().c_str(), isSgReferenceType(typeParam));*/ /* // if the argument is a named variable AND if(varID::isValidVarExp(*itArgs) && // if the argument has an array type, it's contents will be passed by reference OR ((isSgArrayType(typeArg) || isSgPointerType(typeArg)) || // if the argument is a regular variable, by the parameter has a reference type, // or the variable is being passed via a pointer, the variable must be passed by reference isSgReferenceType(typeParam))) { varID argVar(*itArgs); varID paramVar(*itParams); // add this mapping paramArgByRefMap[paramVar] = argVar; }*/ varID argVar = SgExpr2Var(*itArgs); varID paramVar(*itParams); // add this mapping paramArgByRefMap[paramVar] = argVar; /* // if the argument is a non-array variable being passed via a pointer else if(isSgAddressOfOp(*itArgs) && SgPointerType(typeArg) && SgPointerType(typeParam)*/ } }
/*! * \author Markus Schordan * \date 2013. */ void RDTransferFunctions::transferFunctionEntry(Label lab, SgFunctionDefinition* funDef,SgInitializedNamePtrList& formalParameters, Lattice& element0) { RDLattice* element1=dynamic_cast<RDLattice*>(&element0); ROSE_ASSERT(element1); RDLattice& element=*element1; // generate RDs for each parameter variable for(SgInitializedNamePtrList::iterator i=formalParameters.begin(); i!=formalParameters.end(); ++i) { SgInitializedName* formalParameterName=*i; assert(formalParameterName); VariableId formalParameterVarId=_variableIdMapping->variableId(formalParameterName); // it must hold that this VarId does not exist in the RD-element //assert element.insertPair(lab,formalParameterVarId); } }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::IntervalTransferFunctions::transferFunctionEntry(Label lab, SgFunctionDefinition* funDef,SgInitializedNamePtrList& formalParameters, Lattice& element) { // generate Intervals for each parameter variable int paramNr=0; for(SgInitializedNamePtrList::iterator i=formalParameters.begin(); i!=formalParameters.end(); ++i) { SgInitializedName* formalParameterName=*i; VariableId formalParameterVarId=_variableIdMapping->variableId(formalParameterName); IntervalPropertyState* ips=dynamic_cast<IntervalPropertyState*>(&element); // get value of actual parameter VariableId paramId=getParameterVariableId(paramNr); // remove parameter variable ips->addVariable(formalParameterVarId); ips->setVariable(formalParameterVarId,ips->getVariable(paramId)); ips->removeVariable(paramId); paramNr++; } }
void initFuncParams(const Function& func, bool getCompilerGen) { if(funcParams_initialized.find(func) == funcParams_initialized.end()) { SgInitializedNamePtrList params = func.get_params(); for(SgInitializedNamePtrList::iterator itParams = params.begin(); itParams!=params.end(); itParams++) { // skip over compiler-generated names if necessary if(!getCompilerGen && (*itParams)->get_file_info()->isCompilerGenerated()) continue; varID var(*itParams); funcParamVars[func].insert(var); funcParamArrays[func] = arraysFilter(funcParamVars[func]); funcParamScalars[func] = scalarsFilter(funcParamVars[func]); funcParams_initialized.insert(func); } } }
NameQuerySynthesizedAttributeType NameQuery::queryNameArgumentNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; SgFunctionDeclaration *sageFunctionDeclaration = isSgFunctionDeclaration (astNode); if (sageFunctionDeclaration != NULL) { typedef SgInitializedNamePtrList::iterator argumentIterator; SgInitializedNamePtrList sageNameList = sageFunctionDeclaration->get_args (); int countArguments = 0; for (argumentIterator i = sageNameList.begin(); i != sageNameList.end(); ++i) { SgInitializedName* elementNode = *i; ROSE_ASSERT (elementNode != NULL); string sageArgument(elementNode->get_name().str()); returnNameList.push_back(sageArgument.c_str()); countArguments += 1; } #if DEBUG_NAMEQUERY printf ("\nHere is a function declaration :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); cout << "The filename is:" << ROSE:: getFileName (isSgLocatedNode (astNode)) << endl; cout << "The count of arguments is: " << countArguments << endl; #endif } return returnNameList; } /* End function queryNameArgumentNames() */
void getIfConds(SgIfStmt* fixIf, SgScopeStatement* parentScope) { SgStatement* conditional = fixIf->get_conditional(); if (isSgExprStatement(conditional)) { SgExpression* expr = isSgExprStatement(conditional)->get_expression(); std::pair<SgVariableDeclaration*, SgExpression*> pr = SageInterface::createTempVariableForExpression(expr,isSgScopeStatement(fixIf),true); SgInitializedNamePtrList lptr = pr.first->get_variables(); //std::cout << "lprt size: " << lptr.size() << std::endl; ROSE_ASSERT(lptr.size() <= 1); SgVarRefExp* varRef = SageBuilder::buildVarRefExp(pr.first); SgIntVal* iv = SageBuilder::buildIntVal(0); SgNotEqualOp* nop = SageBuilder::buildNotEqualOp(isSgExpression(varRef),isSgExpression(iv)); SgExprStatement* ses = SageBuilder::buildExprStatement(isSgExpression(nop)); SageInterface::replaceStatement(conditional,ses); //SageInterface::moveVariableDeclaration(pr.first, parentScope); // SageInterface::appendStatement(pr.first, parentScope); SageInterface::insertStatementBefore(fixIf,pr.first); std::cout << "conditional type: " << conditional->class_name() << std::endl; } return; }
/*! * \author Markus Schordan * \date 2013, 2015. */ void RDTransferFunctions::transferFunctionEntry(Label lab, SgFunctionDefinition* funDef,SgInitializedNamePtrList& formalParameters, Lattice& element0) { RDLattice& element=dynamic_cast<RDLattice&>(element0); // generate RDs for each parameter variable int paramNr=0; for(SgInitializedNamePtrList::iterator i=formalParameters.begin(); i!=formalParameters.end(); ++i) { // kill parameter variables VariableId paramId=getParameterVariableId(paramNr); element.removeAllPairsWithVariableId(paramId); // generate formal parameter SgInitializedName* formalParameterName=*i; assert(formalParameterName); VariableId formalParameterVarId=getVariableIdMapping()->variableId(formalParameterName); element.insertPair(lab,formalParameterVarId); paramNr++; } }
Rose_STL_Container<SgNode*> NodeQuery::queryNodeVariableDeclarationFromName(SgNode* astNode, SgNode* nameNode){ ROSE_ASSERT( nameNode != NULL ); ROSE_ASSERT( astNode != NULL ); Rose_STL_Container<SgNode*> returnList; if(astNode->variantT() == V_SgVariableDeclaration){ SgName* sageName = isSgName(nameNode); ROSE_ASSERT( sageName != NULL ); std::string nameToMatch = sageName->str(); ROSE_ASSERT( nameToMatch.length() > 0 ); SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration(astNode); ROSE_ASSERT(sageVariableDeclaration != NULL); ROSE_ASSERT( sageVariableDeclaration->get_definition() != NULL ); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); //see if this variable declaration fits the criteria typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator k = sageInitializedNameList.begin (); k != sageInitializedNameList.end(); ++k) { SgInitializedName* elmVar = *k; std::string name = elmVar->get_name().str(); if(name == nameToMatch) returnList.push_back(astNode); } } return returnList; }; /* End function: queryNodeVariableDeclarationFromName */
void mlmFrontend::attachAttribute(SgPragmaDeclaration* pragma, AstAttribute* attr) { // attribute to specify memory level if(isSgVariableDeclaration(getNextStatement(pragma))) { SgVariableDeclaration* decl = isSgVariableDeclaration(getNextStatement(pragma)); ROSE_ASSERT(decl); SgInitializedNamePtrList nameList = decl->get_variables(); if(nameList.size() == 1) { SgInitializedName* initName = nameList[0]; SgSymbol* symbol = initName->get_symbol_from_symbol_table(); symbol->setAttribute("mlmAttribute", attr); } } // attribute to specify tiling level else if(isSgForStatement(getNextStatement(pragma))) { SgForStatement* forStmt = isSgForStatement(getNextStatement(pragma)); ROSE_ASSERT(forStmt); forStmt->setAttribute("mlmAttribute", attr); } }
ForLoop::ForLoop( SgForStatement * l ) : BasicNode(LOOPHEAD), myLoop(l), myLoopType(UNDEFINED), start(NULL), end(NULL), body(NULL), back_edge(NULL), out(NULL), Iter(false) { /* STEP 1 : Get initialization expression and symbol */ SgStatementPtrList stmList = myLoop->get_init_stmt(); if ( stmList.size() != 1 ) { report_error("Too many init statements",l); } else if ( isSgVariableDeclaration(stmList[0]) ) { SgInitializedNamePtrList initList = isSgVariableDeclaration(stmList[0])->get_variables(); if ( initList.size() != 1 ) { report_error("To many induction variables",l); } else { SgInitializedName * initName = initList[0]; if ( isSgAssignInitializer(initName->get_initializer()) ) { symbol = initName->get_name().getString(); start = isSgAssignInitializer(initName->get_initializer())->get_operand(); } else { report_error("Loop initializer is too complecated",initName); } } } else if ( isSgExprStatement(stmList[0]) ) { SgExpression * exp = isSgExprStatement(stmList[0])->get_expression(); if ( isSgAssignOp(exp) ) { SgExpression * lhs = isSgAssignOp(exp)->get_lhs_operand(); SgExpression * rhs = isSgAssignOp(exp)->get_rhs_operand(); if ( isSgVarRefExp(lhs) ) { symbol = isSgVarRefExp(lhs)->get_symbol()->get_name().getString(); start = rhs; } else { report_error("LHS of expression must be a single variable",exp); } } else { report_error("Init expression must be an Assign operation",exp); } } else { report_error("Loop initialization is not recognized",l); } /* STEP 2 : Get the test expression */ SgExprStatement * expStm = isSgExprStatement(myLoop->get_test()); if ( expStm ) { SgExpression * exp = expStm->get_expression(); if ( isSgLessOrEqualOp(exp) ) { SgBinaryOp * binOp = isSgBinaryOp(exp); string name = isSgVarRefExp(isSgBinaryOp(exp)->get_lhs_operand())->get_symbol()->get_name().getString(); if ( name != symbol ) report_error("Loop init and test variable miss-match",exp); end = binOp->get_rhs_operand(); } else if ( isSgLessThanOp(exp) ) { SgBinaryOp * binOp = isSgBinaryOp(exp); string name = isSgVarRefExp(binOp->get_lhs_operand())->get_symbol()->get_name().getString(); if ( name != symbol ) report_error("Loop init and test variable miss-match",exp); SgExpression * tempExp = SageInterface::copyExpression(binOp->get_rhs_operand()); end = buildSubtractOp( tempExp, buildIntVal(1) ); end->set_need_paren(true); tempExp = buildLessOrEqualOp( SageInterface::copyExpression(binOp->get_lhs_operand()), end ); SageInterface::replaceExpression(exp, tempExp, false); } else { report_error("Test expression is not recognized. Re-write the loop or normilize it accordingly",exp); } } else { report_error("Test expression is not recognized. Sorry !", l); } /* STEP 3 : Check the stride */ if ( !isSgPlusPlusOp(l->get_increment()) ) report_error("Increment expression is not recognized. Re-write the loop or normilize it accordingly. Note: Only \"++\" operator supported.",l); /* STEP 4 : Link with Loop Tail node */ back_edge = new ForLoop(start,end,symbol,l,this,this,LOOPTAIL); body = back_edge; }
NodeQuerySynthesizedAttributeType NodeQuery::querySolverVariableTypes (SgNode * astNode) { ROSE_ASSERT (astNode != NULL); NodeQuerySynthesizedAttributeType returnNodeList; /* SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration(astNode); if(sageVariableDeclaration != NULL) { SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables(); printf ("\nHere is a function declaration :Line = %d Columns = %d \n", ROSE:: getLineNumber (isSgLocatedNode(astNode) ), ROSE:: getColumnNumber ( isSgLocatedNode(astNode) )); cout << "The filename is:" << ROSE::getFileName(isSgLocatedNode(astNode)) << endl; typedef SgInitializedNamePtrList::iterator LI; for ( LI i = sageInitializedNameList.begin(); i != sageInitializedNameList.end(); ++i) { SgType* sageElementType = i->get_type(); ROSE_ASSERT( sageElementType != NULL); cout << "The class name is: " << sageElementType->sage_class_name() << endl; returnNodeList.push_back( sageElementType ); } cout << endl << "End printout of this Initialized Name list" << endl; } */ // SgVarRefExp *sageVarRefExp = isSgVarRefExp (astNode); switch (astNode->variantT ()) { case V_SgVariableDeclaration: { SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (astNode); ROSE_ASSERT (sageVariableDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); #if DEBUG_NODEQUERY printf ("\nIn filename: %s ", ROSE::getFileName (isSgLocatedNode (astNode))); printf ("\nHere is a variable :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); //cout << "The typename of the variable is: " << typeName << endl; #endif typedef SgInitializedNamePtrList::iterator variableIterator; SgType *typeNode; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); returnNodeList.push_back (typeNode); } break; } /* End case V_SgVariableDeclaration */ case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: { SgFunctionDeclaration * sageFunctionDeclaration = isSgFunctionDeclaration (astNode); ROSE_ASSERT (sageFunctionDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageFunctionDeclaration->get_args (); SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); returnNodeList.push_back (typeNode); } break; } default: { // DQ (8/20/2005): Added default to avoid compiler warnings about unrepresented cases } } /* End switch case astNode */ return returnNodeList; } /* End function querySolverType() */
NameQuerySynthesizedAttributeType NameQuery::queryVariableNamesWithTypeName (SgNode * astNode, string matchingName) { ROSE_ASSERT (astNode != 0); ROSE_ASSERT (matchingName.length () > 0); NameQuerySynthesizedAttributeType returnNameList; // SgVarRefExp *sageVarRefExp = isSgVarRefExp (astNode); switch (astNode->variantT ()) { case V_SgVariableDeclaration: { SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (astNode); ROSE_ASSERT (sageVariableDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); #if DEBUG_NAMEQUERY printf ("\nIn filename: %s ", ROSE::getFileName (isSgLocatedNode (astNode))); printf ("\nHere is a variable :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); //cout << "The typename of the variable is: " << typeName << endl; #endif SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); string typeName = TransformationSupport::getTypeName(typeNode); if (typeName == matchingName) { string name = elmVar->get_name ().str (); ROSE_ASSERT (name.length () > 0); returnNameList.push_back (name); #if DEBUG_NAMEQUERY cout << "The name of the variable is: " << name << endl; #endif } } break; } /* End case V_SgVariableDeclaration */ case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: { SgFunctionDeclaration * sageFunctionDeclaration = isSgFunctionDeclaration (astNode); ROSE_ASSERT (sageFunctionDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageFunctionDeclaration->get_args (); SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); string typeName = TransformationSupport::getTypeName (typeNode); if (typeName == matchingName) { string name = elmVar->get_name ().str (); ROSE_ASSERT (name.length () > 0); returnNameList.push_back (name); #if DEBUG_NAMEQUERY cout << "The name of the variable is: " << name << endl; #endif } } break; } default: { // DQ (8/20/2005): Added default to avoid compiler warnings about unrepresented cases } } /* End switch case astNode */ return returnNameList; } /* End function NameQuery::queryNameVariableNames() */
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; } } }
void ControlDependenceGraph::_buildInterprocedural() { // Go through the SGNODE dependence nodes and create the appropriate // call site nodes, entry nodes etc. SgFunctionDefinition *func = isSgFunctionDefinition(_head); ROSE_ASSERT(func != NULL); // First create the entry node for the procedure _interprocedural->procedureEntry.entry = new DependenceNode(DependenceNode::ENTRY, func->get_declaration()); DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry); // Link the entry node up with all the nodes in the CDG which do not have // predecessors for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++) { DependenceNode *node = dynamic_cast < DependenceNode * >(*i); if ((node->numPredecessors() == 0) && (node != entry)) { establishEdge(entry, node); } } // create a formal out return argument, control dependent on the entry // node string return_name = func->get_declaration()->get_name().str(); return_name = return_name + " return"; _interprocedural->procedureEntry.formal_return = new DependenceNode(DependenceNode::FORMALOUT, return_name); DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return); establishEdge(entry, formal_return); // for each of the arguments in the function parameter list, add a // formal-in and formal-out node SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList(); SgInitializedNamePtrList params = paramlist->get_args(); for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++) { SgInitializedName *name = *i; DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN, name->get_name().str()); DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT, name->get_name().str()); establishEdge(entry, createNode(formal_in)); establishEdge(entry, createNode(formal_out)); _interprocedural->procedureEntry.formal_in[name] = formal_in; _interprocedural->procedureEntry.formal_out[name] = formal_out; // To preserve the order of arguments, we insert them into arg_order _interprocedural->procedureEntry.arg_order.push_back(name); } // Now we go through each of the SgNodes in our CDG. If any of them // contain a function call, we want to build a call site node for them. map < SgNode *, DependenceNode * >::iterator sgnode_iterator; for (sgnode_iterator = _sgnode_map.begin(); sgnode_iterator != _sgnode_map.end(); sgnode_iterator++) { SgNode *currnode = sgnode_iterator->first; list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode); if (calls.empty()) continue; for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++) { SgFunctionCallExp *call = *i; // This needs to be replaced with some call graph analysis SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function()); ROSE_ASSERT(func != NULL); SgName func_name = func->get_symbol()->get_name(); InterproceduralInfo::CallSiteStructure callstructure; callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call); // the call site is control dependent on the statement (i.e. for // the call site to happen, the statement must be executed) DependenceNode *callsite = createNode(callstructure.callsite); // addLink(callsite, getNode(currnode)); establishEdge(getNode(currnode), callsite); // create an actual out node for the return value, control // dependent on callsite string return_name = func_name.str(); return_name = return_name + " return"; callstructure.actual_return = new DependenceNode(DependenceNode::ACTUALOUT, return_name); DependenceNode *actual_return = createNode(callstructure.actual_return); establishEdge(callsite, actual_return); // For each argument in the function call, build an actual_in and // actual_out, control dependent on callsite SgExpressionPtrList args = call->get_args()->get_expressions(); for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++) { SgExpression *arg = *j; DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg); DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg); establishEdge(callsite, createNode(actual_in)); establishEdge(callsite, createNode(actual_out)); callstructure.actual_in[arg] = actual_in; callstructure.actual_out[arg] = actual_out; // To preserve the order of expressions in the parameter list, // // we insert them into expr_order callstructure.expr_order.push_back(arg); } // add the callstructure to interprocedural info _interprocedural->callsite_map[call] = callstructure; } } }
int main( int argc, char * argv[] ) { // Option to linearize the array. Rose_STL_Container<std::string> localCopy_argv = CommandlineProcessing::generateArgListFromArgcArgv(argc, argv); int newArgc; char** newArgv = NULL; vector<string> argList = localCopy_argv; if (CommandlineProcessing::isOption(argList,"-f2c:","linearize",true) == true) { isLinearlizeArray = true; } CommandlineProcessing::generateArgcArgvFromList(argList,newArgc, newArgv); // Build the AST used by ROSE SgProject* project = frontend(newArgc,newArgv); AstTests::runAllTests(project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000,"_orig"); // Traversal with Memory Pool to search for variableDeclaration variableDeclTraversal translateVariableDeclaration; traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { /* For the Fortran AST, a single variableDeclaration can be shared by multiple variables. This violated the normalization rules for C unparser. Therefore, we have to transform it. */ SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); if((variableDeclaration->get_variables()).size() != 1) { updateVariableDeclarationList(variableDeclaration); statementList.push_back(variableDeclaration); removeList.push_back(variableDeclaration); } } // reset the vector that collects all variable declaration. We need to walk through memory pool again to find types variableDeclList.clear(); traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); SgInitializedNamePtrList initializedNameList = variableDeclaration->get_variables(); for(SgInitializedNamePtrList::iterator i=initializedNameList.begin(); i!=initializedNameList.end();++i) { SgInitializedName* initiallizedName = isSgInitializedName(*i); SgType* baseType = initiallizedName->get_type(); if(baseType->variantT() == V_SgArrayType) { SgArrayType* arrayBase = isSgArrayType(baseType); // At this moment, we are still working on the Fortran-stype AST. Therefore, there is no nested types for multi-dim array. if(arrayBase->findBaseType()->variantT() == V_SgTypeString) { arrayBase->reset_base_type(translateType(arrayBase->findBaseType())); arrayBase->set_rank(arrayBase->get_rank()+1); } } else { initiallizedName->set_type(translateType(baseType)); } } } // replace the AttributeSpecificationStatement Rose_STL_Container<SgNode*> AttributeSpecificationStatement = NodeQuery::querySubTree (project,V_SgAttributeSpecificationStatement); for (Rose_STL_Container<SgNode*>::iterator i = AttributeSpecificationStatement.begin(); i != AttributeSpecificationStatement.end(); i++) { SgAttributeSpecificationStatement* attributeSpecificationStatement = isSgAttributeSpecificationStatement(*i); ROSE_ASSERT(attributeSpecificationStatement); translateAttributeSpecificationStatement(attributeSpecificationStatement); statementList.push_back(attributeSpecificationStatement); removeList.push_back(attributeSpecificationStatement); } // replace the parameter reference parameterTraversal translateParameterRef; traverseMemoryPoolVisitorPattern(translateParameterRef); for(vector<SgVarRefExp*>::iterator i=parameterRefList.begin(); i!=parameterRefList.end(); ++i) { SgVarRefExp* parameterRef = isSgVarRefExp(*i); if(parameterSymbolList.find(parameterRef->get_symbol()) != parameterSymbolList.end()) { SgExpression* newExpr = isSgExpression(deepCopy(parameterSymbolList.find(parameterRef->get_symbol())->second)); ROSE_ASSERT(newExpr); newExpr->set_parent(parameterRef->get_parent()); replaceExpression(parameterRef, newExpr, false); } } /* Parameters will be replaced by #define, all the declarations should be removed */ for(map<SgVariableSymbol*,SgExpression*>::iterator i=parameterSymbolList.begin();i!=parameterSymbolList.end();++i) { SgVariableSymbol* symbol = i->first; SgInitializedName* initializedName = symbol->get_declaration(); SgVariableDeclaration* decl = isSgVariableDeclaration(initializedName->get_parent()); statementList.push_back(decl); removeList.push_back(decl); } // Traversal with Memory Pool to search for arrayType arrayTypeTraversal translateArrayType; traverseMemoryPoolVisitorPattern(translateArrayType); for(vector<SgArrayType*>::iterator i=arrayTypeList.begin(); i!=arrayTypeList.end(); ++i) { if(isLinearlizeArray) { linearizeArrayDeclaration(*i); } else { translateArrayDeclaration(*i); } } // Traversal with Memory Pool to search for pntrArrRefExp pntrArrRefTraversal translatePntrArrRefExp; traverseMemoryPoolVisitorPattern(translatePntrArrRefExp); for(vector<SgPntrArrRefExp*>::iterator i=pntrArrRefList.begin(); i!=pntrArrRefList.end(); ++i) { if(isLinearlizeArray) { linearizeArraySubscript(*i); } else { translateArraySubscript(*i); } } Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); for (Rose_STL_Container<SgNode*>::iterator i = functionList.begin(); i != functionList.end(); i++) { if((isSgProcedureHeaderStatement(*i) != NULL) || (isSgProgramHeaderStatement(*i) != NULL)){ SgFunctionDeclaration* functionBody = isSgFunctionDeclaration(*i); bool hasReturnVal = false; if(isSgProcedureHeaderStatement(functionBody)) { hasReturnVal = isSgProcedureHeaderStatement(functionBody)->isFunction(); } fixFortranSymbolTable(functionBody->get_definition(),hasReturnVal); } } // Traversal with Memory Pool to search for equivalenceStatement equivalencelTraversal translateEquivalenceStmt; traverseMemoryPoolVisitorPattern(translateEquivalenceStmt); for(vector<SgEquivalenceStatement*>::iterator i=equivalenceList.begin(); i!=equivalenceList.end(); ++i) { SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(*i); ROSE_ASSERT(equivalenceStatement); translateEquivalenceStatement(equivalenceStatement); statementList.push_back(equivalenceStatement); removeList.push_back(equivalenceStatement); } // Simple traversal, bottom-up, to translate the rest f2cTraversal f2c; f2c.traverseInputFiles(project,postorder); // removing all the unsed statement from AST for(vector<SgStatement*>::iterator i=statementList.begin(); i!=statementList.end(); ++i) { removeStatement(*i); (*i)->set_parent(NULL); } // deepDelete the removed nodes for(vector<SgNode*>::iterator i=removeList.begin(); i!=removeList.end(); ++i) { deepDelete(*i); } /* 1. There should be no Fortran-specific AST nodes in the whole AST graph after the translation. TODO: make sure translator generating clean AST */ //generateDOT(*project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000); return backend(project); }
//Generates SSA form numbers for the variables contained in the CFG node labeled *label and attaches them as AstValueAttributes to the related SgNodes //Generates phi statements for the node if it is an if node; Collects those phi statements in a phi attribute and attaches it to the related SgNode //Continues the traversal of the CFG; The CFG nodes are traversed in the topological order that treats if nodes as follows: //if node -> true branch -> false branch -> (phi statements for the if node are now finished) -> if node's associated continue node and its successors //Assumption: The node is located in in the inTrueBranch branch of the if node labeled *condLabel (These two arguments are required to generate the SSA form numbers) void SSAGenerator::processNode(Label* label, Label* condLabel, bool inTrueBranch) { SgNode* node = labeler->getNode(*label); LabelSet successors = flow->succ(*label); assert(successors.size() <= 2); //Skip the current node if it is just a return node for a called function if(labeler->isFunctionCallReturnLabel(*label)) { logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "Ignoring function call return node " << *label << endl; assert(successors.size() == 1); Label nextLabel = *successors.begin(); //If the next node is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(!isExitOrContOfPred(&nextLabel, label)) processNode(&nextLabel, condLabel, inTrueBranch); return; } logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "processNode() called for label " << *label << endl; SgVariableDeclaration* varDec = dynamic_cast<SgVariableDeclaration*>(node); SgExprStatement* exprStmt = dynamic_cast<SgExprStatement*>(node); if(varDec) //Variable declaration { SgInitializedNamePtrList varNames = varDec->get_variables(); SgInitializedNamePtrList::iterator i = varNames.begin(); while(i != varNames.end()) { string name = (*i)->get_qualified_name(); //Update the varsDeclaredInTrueBranch/varsDeclaredInFalseBranch attribute in the PhiAttribute of the condition node if(condLabel != NULL) { SgNode* condNode = labeler->getNode(*condLabel); AstAttribute* condAtt = condNode->getAttribute("PHI"); assert(condAtt != NULL); PhiAttribute* condPhiAtt = dynamic_cast<PhiAttribute*>(condAtt); assert(condPhiAtt != NULL); if(inTrueBranch) condPhiAtt->varsDeclaredInTrueBranch.insert(name); else condPhiAtt->varsDeclaredInFalseBranch.insert(name); } SgAssignInitializer* assignInit = dynamic_cast<SgAssignInitializer*>((*i)->get_initializer()); if(assignInit) //Declaration with initialization { SgExpression* ex = assignInit->get_operand(); processSgExpression(ex, condLabel, inTrueBranch); } else //Declaration without initialization { assert((*i)->get_initializer() == NULL); } //Assign number to declared variable int number = nextNumber(name, condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Next number for variable " << name << ": " << number << endl; AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(number); (*i)->setAttribute("SSA_NUMBER", numberAtt); i++; } } else if(exprStmt) //Assignment to variable or if statement or function call or ... { SgExpression* ex = exprStmt->get_expression(); processSgExpression(ex, condLabel, inTrueBranch); } else //CFG node that is not a variable declaration and not an expression statement; Should only be the case for the first node (Entry), the last node (Exit) and return nodes { logger[Sawyer::Message::DEBUG] << "Node is not a variable declaration and not an expression statement" << endl; SgReturnStmt* retStmt = dynamic_cast<SgReturnStmt*>(node); assert(labeler->isFunctionEntryLabel(*label) || labeler->isFunctionExitLabel(*label) || retStmt != NULL); } //Continue traversal of CFG if(successors.size() == 1) //Current node is a regular node (not an if node) { Label nextLabel = *successors.begin(); //If the next node is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(!isExitOrContOfPred(&nextLabel, label)) processNode(&nextLabel, condLabel, inTrueBranch); } else if(successors.size() == 2) //Current node is an if node { assert(exprStmt != NULL); //Attach PhiAttribute to node that (for now) only includes its reaching variable numbers map<string, int> reachingNumbers = currentNumberMap; if(condLabel != NULL) { SgNode* condNode = labeler->getNode(*condLabel); AstAttribute* condAtt = condNode->getAttribute("PHI"); assert(condAtt != NULL); PhiAttribute* condPhiAtt = dynamic_cast<PhiAttribute*>(condAtt); assert(condPhiAtt != NULL); map<string, int>::iterator m = reachingNumbers.begin(); while(m != reachingNumbers.end()) { //m->first is in scope at the current node only if it is in scope at the condition node or it is declared locally in the current node's branch of the condition node bool inScope = (condPhiAtt->reachingNumbers.find(m->first) != condPhiAtt->reachingNumbers.end()) || (inTrueBranch && condPhiAtt->varsDeclaredInTrueBranch.find(m->first) != condPhiAtt->varsDeclaredInTrueBranch.end()) || (!inTrueBranch && condPhiAtt->varsDeclaredInFalseBranch.find(m->first) != condPhiAtt->varsDeclaredInFalseBranch.end()); if(!inScope) { m = reachingNumbers.erase(m); continue; } //Reaching number for m->first has to be updated //TODO: Makes no sense to take reaching numbers from current numbers in the first place m->second = currentNumber(m->first, condLabel, inTrueBranch); m++; } } CondAtomic* cond = new CondAtomic(*label); PhiAttribute* phiAtt = new PhiAttribute(reachingNumbers, cond); exprStmt->setAttribute("PHI", phiAtt); //Identify true successor, false successor and continue node Flow trueOutEdges = flow->outEdgesOfType(*label, EDGE_TRUE); Flow falseOutEdges = flow->outEdgesOfType(*label, EDGE_FALSE); assert( (trueOutEdges.size() == 1) && (falseOutEdges.size() == 1) ); Edge outTrue = *trueOutEdges.begin(); Edge outFalse = *falseOutEdges.begin(); Label nextLabelTrue = outTrue.target(); Label nextLabelFalse = outFalse.target(); Label* contLabel = getContinueLabel(*label); //Process true and false branch ContNodeAttribute* contAttr = getContinueNodeAttr(*label); bool commitPhiStatements = true; //"Hack": //If one or both of the two branches definitely return there will be phi statements created for the current node although the SSA form that is being created here does not require them in that case //They are however required to find out current variable numbers in the branch/branches that definitely return //Therefore in that case the phi statements will be created but not committed if (contAttr == NULL) //Both branches definitely return { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); //"Hack" if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); //"Hack" commitPhiStatements = false; } else if (contAttr->trueBranchReturns == YES && contAttr->falseBranchReturns != YES) //Only the true branch definitely returns { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); //"Hack" if(condLabel == NULL) //No enclosing condition node exists { //"Hack"-phi-statement needs to be used to determine current variable numbers because processing the true branch modified currentNumberMap if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, inTrueBranch); } else if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, condLabel, inTrueBranch); commitPhiStatements = false; } else if (contAttr->trueBranchReturns != YES && contAttr->falseBranchReturns == YES) //Only the false branch definitely returns { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, condLabel, inTrueBranch); if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); //"Hack" commitPhiStatements = false; } else //Neither of the two branches definitely returns { assert(!(contAttr->trueBranchReturns == YES && contAttr->falseBranchReturns == YES)); if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); commitPhiStatements = true; } if(commitPhiStatements) //Commit phi statements: Generate a new number for the variable of each phi statement and save that number in its respective newNumber attribute { vector<PhiStatement*>::iterator i = phiAtt->phiStatements.begin(); logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "Phi statements created for node with label " << *label << ":" << endl; while (i != phiAtt->phiStatements.end()) { if((*i)->trueNumber != (*i)->falseNumber) { //Generate new number for phi statement's variable int newNumber = nextNumber((*i)->varName, condLabel, inTrueBranch); (*i)->newNumber = newNumber; logger[Sawyer::Message::DEBUG] << (*i)->toString() << endl; } i++; } logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "COMPLETE PHI ATTRIBUTE:" << endl << phiAtt->toString() << endl; } else //Delete phi statements ("Hack") { phiAtt->phiStatements.clear(); } //If the continue node exists and is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(contLabel != NULL && !isExitOrContOfPred(contLabel, label)) { processNode(contLabel, condLabel, inTrueBranch); } } }