void CompassAnalyses::FloatingPointExactComparison::Traversal:: visit(SgNode* node) { // Implement your traversal here. SgExprStatement* exprStatement = NULL; SgIfStmt* ifStmt = isSgIfStmt(node); if(NULL != ifStmt) exprStatement = isSgExprStatement(ifStmt->get_conditional()); SgWhileStmt* whileStmt = isSgWhileStmt(node); if(NULL != whileStmt) exprStatement = isSgExprStatement(whileStmt->get_condition()); SgDoWhileStmt* doWhileStmt = isSgDoWhileStmt(node); if(NULL != doWhileStmt) exprStatement = isSgExprStatement(doWhileStmt->get_condition()); SgForStatement* forStatement = isSgForStatement(node); if(NULL != forStatement) exprStatement = isSgExprStatement(forStatement->get_test()); if(NULL != exprStatement && NULL != isSgNotEqualOp(exprStatement->get_expression())) { SgNotEqualOp* comparison = isSgNotEqualOp(exprStatement->get_expression()); if((comparison->get_lhs_operand_i() != NULL && isSgDoubleVal(comparison->get_lhs_operand_i()) != NULL) || (comparison->get_rhs_operand_i() != NULL && isSgDoubleVal(comparison->get_rhs_operand_i()) != NULL)) { output->addOutput(new CheckerOutput(comparison)); } } if(NULL != exprStatement && NULL != isSgEqualityOp(exprStatement->get_expression())) { SgEqualityOp* comparison = isSgEqualityOp(exprStatement->get_expression()); if((comparison->get_lhs_operand_i() != NULL && isSgDoubleVal(comparison->get_lhs_operand_i()) != NULL) || (comparison->get_rhs_operand_i() != NULL && isSgDoubleVal(comparison->get_rhs_operand_i()) != NULL)) { output->addOutput(new CheckerOutput(comparison)); } } } //End of the visit function.
virtual void visit (SgNode * node) { SgExprStatement * isExprStatement = isSgExprStatement ( node ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (?). Probably not in OP2 * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } }
void Unparse_Jovial::unparseSwitchStmt(SgStatement* stmt, SgUnparse_Info& info) { // Sage node corresponding to Jovial CaseStatement; SgSwitchStatement* switch_stmt = isSgSwitchStatement(stmt); ROSE_ASSERT(switch_stmt != NULL); curprint("CASE "); SgExprStatement* expressionStatement = isSgExprStatement(switch_stmt->get_item_selector()); ROSE_ASSERT(expressionStatement != NULL); unparseExpression(expressionStatement->get_expression(), info); curprint(";"); unp->cur.insert_newline(1); curprint("BEGIN"); unp->cur.insert_newline(1); if (switch_stmt->get_body()) { unparseStatement(switch_stmt->get_body(), info); } unp->cur.insert_newline(1); curprint("END"); unp->cur.insert_newline(1); unp->cur.insert_newline(1); }
void Unparse_Jovial::unparseIfStmt(SgStatement* stmt, SgUnparse_Info& info) { SgIfStmt* if_stmt = isSgIfStmt(stmt); ROSE_ASSERT(if_stmt != NULL); ROSE_ASSERT(if_stmt->get_conditional()); // condition curprint("IF ("); info.set_inConditional(); SgExprStatement* expressionStatement = isSgExprStatement(if_stmt->get_conditional()); unparseExpression(expressionStatement->get_expression(), info); info.unset_inConditional(); curprint(") ;"); unp->cur.insert_newline(1); // true body ROSE_ASSERT(if_stmt->get_true_body()); unparseStatement(if_stmt->get_true_body(), info); // false body if (if_stmt->get_false_body() != NULL) { curprint("ELSE"); unp->cur.insert_newline(1); unparseStatement(if_stmt->get_false_body(), info); } }
virtual void visit(SgNode* n) { if (isSgBasicBlock(n)) { SgBasicBlock* bb = isSgBasicBlock(n); SgStatementPtrList& stmts = bb->get_statements(); size_t initi; for (size_t decli = 0; decli < stmts.size(); ++decli) { if (isSgVariableDeclaration(stmts[decli])) { SgVariableDeclaration* decl = isSgVariableDeclaration(stmts[decli]); SgInitializedNamePtrList& vars = decl->get_variables(); for (size_t vari = 0; vari != vars.size(); ++vari) { SgInitializedName* in = vars[vari]; if (in->get_initializer() == 0) { bool used = false; for (initi = decli + 1; initi < stmts.size(); used |= containsVariableReference(stmts[initi], in), ++initi) { SgExprStatement* initExprStmt = isSgExprStatement(stmts[initi]); if (initExprStmt) { SgExpression* top = initExprStmt->get_expression(); if (isSgAssignOp(top)) { SgVarRefExp* vr = isSgVarRefExp(isSgAssignOp(top)->get_lhs_operand()); ROSE_ASSERT(isSgAssignOp(top) != NULL); SgExpression* newinit = isSgAssignOp(top)->get_rhs_operand(); if (!used && vr && vr->get_symbol()->get_declaration() == in) { ROSE_ASSERT(newinit != NULL); // printf ("MoveDeclarationsToFirstUseVisitor::visit(): newinit = %p = %s \n",newinit,newinit->class_name().c_str()); ROSE_ASSERT(newinit->get_type() != NULL); SgAssignInitializer* i = new SgAssignInitializer(SgNULL_FILE,newinit,newinit->get_type()); i->set_endOfConstruct(SgNULL_FILE); // printf ("Built a SgAssignInitializer #1 \n"); vars[vari]->set_initializer(i); stmts[initi] = decl; newinit->set_parent(i); // DQ (6/23/2006): Set the parent and file_info pointers // printf ("Setting parent of i = %p = %s to parent = %p = %s \n",i,i->class_name().c_str(),in,in->class_name().c_str()); i->set_parent(in); ROSE_ASSERT(i->get_parent() != NULL); i->set_file_info(new Sg_File_Info(*(newinit->get_file_info()))); ROSE_ASSERT(i->get_file_info() != NULL); // Assumes only one var per declaration FIXME ROSE_ASSERT (vars.size() == 1); stmts.erase(stmts.begin() + decli); --decli; // To counteract ++decli in loop header break; // To get out of initi loop } } } } } } } } } }
void CompassAnalyses::ExplicitTestForNonBooleanValue::Traversal:: visit(SgNode* node) { // Implement your traversal here. // 1. conditional expression if(NULL != isSgBasicBlock(node)) { Rose_STL_Container<SgNode*> conditionalExpList = NodeQuery::querySubTree(node, V_SgConditionalExp); for(Rose_STL_Container<SgNode*>::iterator i=conditionalExpList.begin(); i != conditionalExpList.end(); i++) { SgConditionalExp* conditionalExp = isSgConditionalExp(*i); //ROSE_ASSERT(conditionalExp != NULL); if(NULL != conditionalExp && NULL != isSgCastExp(conditionalExp->get_conditional_exp())) { output->addOutput(new CheckerOutput(conditionalExp)); } } } else { SgExprStatement* exprStatement = NULL; // 2. test statement in a if statement SgIfStmt* ifStmt = isSgIfStmt(node); if(NULL != ifStmt) exprStatement = isSgExprStatement(ifStmt->get_conditional()); // 3. test statement in a while statement SgWhileStmt* whileStmt = isSgWhileStmt(node); if(NULL != whileStmt) exprStatement = isSgExprStatement(whileStmt->get_condition()); // 4. test statement in a do-while statement SgDoWhileStmt* doWhileStmt = isSgDoWhileStmt(node); if(NULL != doWhileStmt) exprStatement = isSgExprStatement(doWhileStmt->get_condition()); // 5. test statement in a for statement SgForStatement* forStatement = isSgForStatement(node); if(NULL != forStatement) exprStatement = isSgExprStatement(forStatement->get_test()); if(NULL != exprStatement && NULL != isSgCastExp(exprStatement->get_expression())) { output->addOutput(new CheckerOutput(node)); } } } //End of the visit function.
bool isHtThreadControlStmt(SgStatement *S) { SgExprStatement *es = isSgExprStatement(S); SgFunctionCallExp *fce = 0; if (es && (fce = isSgFunctionCallExp(es->get_expression()))) { SgFunctionDeclaration *calleeFD = fce->getAssociatedFunctionDeclaration(); std::string fname = calleeFD->get_name().getString(); size_t pos = 0; if (fname == "WriteMemPause" || fname == "ReadMemPause" || fname == "HtBarrier" || (((pos = fname.find("SendCall_")) != std::string::npos /* || (pos = fname.find("SendCallFork_")) != std::string::npos */ || (pos = fname.find("SendReturn_")) != std::string::npos || (pos = fname.find("RecvReturnJoin_")) != std::string::npos) && pos == 0)) { return true; } } return false; }
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; }
void FortranCUDAUserSubroutine::createStatements () { using namespace SageInterface; using boost::iequals; using std::string; using std::vector; class TreeVisitor: public AstSimpleProcessing { private: /* * ====================================================== * The recursive visit of a user subroutine populates * this vector with successive function calls which are * then appended after the visit * ====================================================== */ vector < SgProcedureHeaderStatement * > calledRoutines; public: vector < SgProcedureHeaderStatement * > getCalledRoutinesInStatement() { return calledRoutines; } TreeVisitor () { } virtual void visit (SgNode * node) { SgExprStatement * isExprStatement = isSgExprStatement ( node ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (?). Probably not in OP2 * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } } }; Debug::getInstance ()->debugMessage ("User subroutine: outputting and modifying statements", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); SgFunctionParameterList * originalParameters = originalSubroutine->get_parameterList (); vector <SgStatement *> originalStatements = originalSubroutine->get_definition ()->get_body ()->get_statements (); for (vector <SgStatement *>::iterator it = originalStatements.begin (); it != originalStatements.end (); ++it) { SgExprStatement * isExprStatement = isSgExprStatement ( *it ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (probably not in OP2) * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } SgVariableDeclaration * isVariableDeclaration = isSgVariableDeclaration ( *it); if (isVariableDeclaration == NULL) { /* * ====================================================== * Do not append use statement, because other subroutines * are directly appended to the CUDA module * ====================================================== */ SgUseStatement * isUseStmt = isSgUseStatement ( *it ); if (isUseStmt != NULL) { Debug::getInstance ()->debugMessage ( "Not appending use statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); } else { Debug::getInstance ()->debugMessage ( "Appending (non-variable-declaration) statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); appendStatement (*it, subroutineScope); /* * ====================================================== * Recursively look for subroutine calls inside shallow * nodes in the routines (e.g. when a call is inside an * if). After the visit get the generated vector of names * and append it to the userSubroutine vector * ====================================================== */ TreeVisitor * visitor = new TreeVisitor (); visitor->traverse (*it, preorder); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); vector < SgProcedureHeaderStatement * > deepStatementCalls = visitor->getCalledRoutinesInStatement (); vector < SgProcedureHeaderStatement * >::iterator itDeepCalls; for (itDeepCalls = deepStatementCalls.begin(); itDeepCalls != deepStatementCalls.end(); ++itDeepCalls) calledRoutines.push_back (*itDeepCalls); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } } else { Debug::getInstance ()->debugMessage ("Appending variable declaration", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); unsigned int OP_DAT_ArgumentGroup = 1; for (SgInitializedNamePtrList::iterator variableIt = isVariableDeclaration->get_variables ().begin (); variableIt != isVariableDeclaration->get_variables ().end (); ++variableIt) { string const variableName = (*variableIt)->get_name ().getString (); SgType * type = (*variableIt)->get_typeptr (); /* * ====================================================== * Specification of "value" attribute is only * for user kernels. Our call convention is that * in all deeper level calls we always pass parameters * by reference (see else branch below) * ====================================================== */ bool isFormalParamater = false; for (SgInitializedNamePtrList::iterator paramIt = originalParameters->get_args ().begin (); paramIt != originalParameters->get_args ().end (); ++paramIt, ++OP_DAT_ArgumentGroup) { string const formalParamterName = (*paramIt)->get_name ().getString (); if (iequals (variableName, formalParamterName)) { isFormalParamater = true; if (parallelLoop->isIndirect (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is an INDIRECT formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration; if ( isUserKernel == true ) variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); ROSE_ASSERT ( variableDeclaration != NULL ); } else if (parallelLoop->isGlobal (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a GLOBAL formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } else { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a formal parameter " + parallelLoop->getOpDatInformation (OP_DAT_ArgumentGroup), Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); if ( isUserKernel == true ) SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } } } if (isFormalParamater == false) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is NOT a formal parameter", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclaration ( variableName, type, subroutineScope); } } } } }
InheritedAttribute visitorTraversal::evaluateInheritedAttribute(SgNode* n, InheritedAttribute inheritedAttribute) { Sg_File_Info* s = n->get_startOfConstruct(); Sg_File_Info* e = n->get_endOfConstruct(); Sg_File_Info* f = n->get_file_info(); for(int x=0; x < inheritedAttribute.depth; ++x) { printf(" "); } if(s != NULL && e != NULL && !isSgLabelStatement(n)) { printf ("%s (%d, %d, %d)->(%d, %d): %s",n->sage_class_name(),s->get_file_id()+1,s->get_raw_line(),s->get_raw_col(),e->get_raw_line(),e->get_raw_col(), verbose ? n->unparseToString().c_str() : "" ); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } SgExprStatement * exprStmt = isSgExprStatement(n); if(exprStmt != NULL) { printf(" [expr type: %s]", exprStmt->get_expression()->sage_class_name()); SgFunctionCallExp * fcall = isSgFunctionCallExp(exprStmt->get_expression()); if(fcall != NULL) { SgExpression * funcExpr = fcall->get_function(); if(funcExpr != NULL) { printf(" [function expr: %s]", funcExpr->class_name().c_str()); } SgFunctionDeclaration * fdecl = fcall->getAssociatedFunctionDeclaration(); if(fdecl != NULL) { printf(" [called function: %s]", fdecl->get_name().str()); } } } if(isSgFunctionDeclaration(n)) { printf(" [declares function: %s]", isSgFunctionDeclaration(n)->get_name().str()); } SgStatement * sgStmt = isSgStatement(n); if(sgStmt != NULL) { printf(" [scope: %s, %p]", sgStmt->get_scope()->sage_class_name(), sgStmt->get_scope()); } //SgLabelStatement * lblStmt = isSgLabelStatement(n); //if(lblStmt != NULL) { // SgStatement * lblStmt2 = lblStmt->get_statement(); //} } else if (f != NULL) { SgInitializedName * iname = isSgInitializedName(n); if(iname != NULL) { SgType* inameType = iname->get_type(); printf("%s (%d, %d, %d): %s [type: %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(),n->unparseToString().c_str(),inameType->class_name().c_str()); SgDeclarationStatement * ds = isSgDeclarationStatement(iname->get_parent()); if(ds != NULL) { if(ds->get_declarationModifier().get_storageModifier().isStatic()) { printf(" static"); } } SgArrayType * art = isSgArrayType(iname->get_type()); if(art != NULL) { printf(" %d", art->get_rank()); } printf("]"); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } else { printf("%s (%d, %d, %d): %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(), verbose ? n->unparseToString().c_str() : ""); } } else { printf("%s : %s", n->sage_class_name(), verbose ? n->unparseToString().c_str() : ""); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } printf(" succ# %lu", n->get_numberOfTraversalSuccessors()); printf("\n"); return InheritedAttribute(inheritedAttribute.depth+1); }
//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); } } }
bool ArrayAssignmentStatementTransformation::targetForTransformation(SgNode* astNode) { // This is a static function which returns true when the current node // of the AST is a target for transformation. bool returnValue = FALSE; ROSE_ASSERT (astNode != NULL); // This code used to recognize array statements checks to see if the name of the type of the // function contained in the expression statement is "doubleArray". This code will be // dramatically simplified once we can use the higher level grammars to recognise array // statements. At present this code is not a robust test for the use existence of a transformable // array statement it will be robust once we can use the higher level grammars (AST restructuring // tools) generated by ROSETTA. SgExprStatement *expressionStatement = isSgExprStatement(astNode); // In this example we only perform transformations on declaration statements if (expressionStatement != NULL) { SgExpression* expression = expressionStatement->get_expression(); ROSE_ASSERT (expression != NULL); // See if this is an A++ member function call SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(expression); // ROSE_ASSERT (functionCallExp != NULL); if (functionCallExp != NULL) { SgType* type = functionCallExp->get_type(); ROSE_ASSERT (type != NULL); SgClassType* classType = isSgClassType(type); if (classType == NULL) { // Check to see if it a reference to a class type (and get it's base type) SgType* type = functionCallExp->get_type(); ROSE_ASSERT (type != NULL); SgReferenceType* referenceType = isSgReferenceType(type); if (referenceType != NULL) { ROSE_ASSERT (referenceType != NULL); SgType* baseType = referenceType->get_base_type(); ROSE_ASSERT (baseType != NULL); classType = isSgClassType(baseType); ROSE_ASSERT (classType != NULL); } else { return FALSE; } } ROSE_ASSERT (classType != NULL); // It is the get_name which returns the type name (not the qualified name (I forget what it is for) SgName name = classType->get_name(); if (name == "intArray" || name == "floatArray" || name == "doubleArray") { #if DEBUG printf( "ArrayAssignmentStatementTransformation::targetForTransformation Expression Statement %s \n", expressionStatement->unparseToString().c_str()); #endif returnValue = TRUE; } else { printf( "Not a expression statement containing a function call expression of type {double,float,int}Array ... \n"); } } else { // This case could be "A;" in which case there is no transformation printf("Not a expression statement containing a function call expression ... \n"); } } else { // printf ("Not an expression statement (only expression statements qualify!) \n"); } return returnValue; }
// Do finite differencing on one expression within one context. The expression // must be defined and valid within the entire body of root. The rewrite rules // are used to simplify expressions. When a variable var is updated from // old_value to new_value, an expression of the form (var, (old_value, // new_value)) is created and rewritten. The rewrite rules may either produce // an arbitrary expression (which will be used as-is) or one of the form (var, // (something, value)) (which will be changed to (var = value)). void doFiniteDifferencingOne(SgExpression* e, SgBasicBlock* root, RewriteRule* rules) { SgStatementPtrList& root_stmts = root->get_statements(); SgStatementPtrList::iterator i; for (i = root_stmts.begin(); i != root_stmts.end(); ++i) { if (expressionComputedIn(e, *i)) break; } if (i == root_stmts.end()) return; // Expression is not used within root, so quit vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e); SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter; SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */); SgInitializedName* cachevar = cachedecl->get_variables().back(); ROSE_ASSERT (cachevar); root->get_statements().insert(i, cachedecl); cachedecl->set_parent(root); cachedecl->set_definingDeclaration(cachedecl); cachevar->set_scope(root); SgVariableSymbol* sym = new SgVariableSymbol(cachevar); root->insert_symbol(cachename, sym); SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym); vr->set_endOfConstruct(SgNULL_FILE); replaceCopiesOfExpression(e, vr, root); vector<SgExpression*> modifications_to_used_symbols; FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root); cachedecl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + cachename.str() + " is a cache of " + e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before)); if (modifications_to_used_symbols.size() == 0) { SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e); e->set_parent(cacheinit); cachevar->set_initializer(cacheinit); cacheinit->set_parent(cachevar); } else { for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i) { SgExpression* modstmt = modifications_to_used_symbols[i]; #ifdef FD_DEBUG cout << "Updating cache after " << modstmt->unparseToString() << endl; #endif SgExpression* updateCache = 0; SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym); varref->set_endOfConstruct(SgNULL_FILE); SgTreeCopy tc; SgExpression* eCopy = isSgExpression(e->copy(tc)); switch (modstmt->variantT()) { case V_SgAssignOp: { SgAssignOp* assignment = isSgAssignOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); replaceCopiesOfExpression(lhs, rhs, eCopy); } break; case V_SgPlusAssignOp: case V_SgMinusAssignOp: case V_SgAndAssignOp: case V_SgIorAssignOp: case V_SgMultAssignOp: case V_SgDivAssignOp: case V_SgModAssignOp: case V_SgXorAssignOp: case V_SgLshiftAssignOp: case V_SgRshiftAssignOp: { SgBinaryOp* assignment = isSgBinaryOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); SgTreeCopy tc; SgExpression* rhsCopy = isSgExpression(rhs->copy(tc)); SgExpression* newval = 0; switch (modstmt->variantT()) { #define DO_OP(op, nonassignment) \ case V_##op: { \ newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \ newval->set_endOfConstruct(SgNULL_FILE); \ } \ break DO_OP(SgPlusAssignOp, SgAddOp); DO_OP(SgMinusAssignOp, SgSubtractOp); DO_OP(SgAndAssignOp, SgBitAndOp); DO_OP(SgIorAssignOp, SgBitOrOp); DO_OP(SgMultAssignOp, SgMultiplyOp); DO_OP(SgDivAssignOp, SgDivideOp); DO_OP(SgModAssignOp, SgModOp); DO_OP(SgXorAssignOp, SgBitXorOp); DO_OP(SgLshiftAssignOp, SgLshiftOp); DO_OP(SgRshiftAssignOp, SgRshiftOp); #undef DO_OP default: break; } assert (newval); replaceCopiesOfExpression(lhs, newval, eCopy); } break; case V_SgPlusPlusOp: { SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one); add->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(add); one->set_parent(add); replaceCopiesOfExpression(lhs,add,eCopy); } break; case V_SgMinusMinusOp: { SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one); sub->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(sub); one->set_parent(sub); replaceCopiesOfExpression(lhs,sub,eCopy); } break; default: cerr << modstmt->sage_class_name() << endl; assert (false); break; } #ifdef FD_DEBUG cout << "e is " << e->unparseToString() << endl; cout << "eCopy is " << eCopy->unparseToString() << endl; #endif updateCache = doFdVariableUpdate(rules, varref, e, eCopy); #ifdef FD_DEBUG cout << "updateCache is " << updateCache->unparseToString() << endl; #endif if (updateCache) { ROSE_ASSERT(modstmt != NULL); SgNode* ifp = modstmt->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt); modstmt->set_parent(comma); updateCache->set_parent(comma); if (ifp == NULL) { printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str()); modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug"); } ROSE_ASSERT(ifp != NULL); #ifdef FD_DEBUG cout << "New expression is " << comma->unparseToString() << endl; cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl; #endif if (isSgExpression(ifp)) { isSgExpression(ifp)->replace_expression(modstmt, comma); comma->set_parent(ifp); } else { // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!) // cerr << ifp->sage_class_name() << endl; // assert (!"Bad parent type for inserting comma expression"); SgStatement* statement = isSgStatement(ifp); if (statement != NULL) { #ifdef FD_DEBUG printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str()); SgExprStatement* expresionStatement = isSgExprStatement(statement); if (expresionStatement != NULL) { SgExpression* expression = expresionStatement->get_expression(); printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str()); } #endif statement->replace_expression(modstmt, comma); comma->set_parent(statement); } else { ROSE_ASSERT(ifp != NULL); printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str()); ROSE_ASSERT(false); } } #ifdef FD_DEBUG cout << "IFP is now " << ifp->unparseToString() << endl; #endif } } } }