static bool ContainsNonSimpleCall(SgStatement *stmt) { static std::set< std::string > segDB ; bool containsUnknownCall = false ; if (segDB.empty()) { char funcName[128] ; FILE *fp ; if ((fp = fopen("SegDB.txt", "r")) != NULL) { while(fgets(funcName, 128, fp)) { funcName[strlen(funcName)-1] = 0 ; segDB.insert(funcName) ; } fclose(fp) ; } else { printf("File SEGDB.txt is absent. Sequential segment results degraded.\n") ; segDB.insert("_____") ; } } /* check to see if this statement contains any function calls */ Rose_STL_Container<SgNode*> calls = NodeQuery::querySubTree(stmt, V_SgFunctionCallExp) ; for (Rose_STL_Container<SgNode*>::iterator c_itr = calls.begin(); c_itr != calls.end(); ++c_itr) { SgFunctionCallExp *stmt = isSgFunctionCallExp(*c_itr) ; ROSE_ASSERT(stmt); SgFunctionRefExp *func = isSgFunctionRefExp(stmt->get_function()) ; if (func != NULL) { SgFunctionSymbol *funcName = func->get_symbol() ; if (segDB.find(funcName->get_name().getString()) == segDB.end()) { containsUnknownCall = true ; break ; } } else { /* Since I can't handle this case, assume the worst -- for now */ containsUnknownCall = true ; break ; } } return containsUnknownCall ; }
virtual void visit(SgNode *node) { /*override*/ SgFunctionCallExp *fcall = isSgFunctionCallExp(node); SgFunctionDeclaration *fdecl = fcall ? fcall->getAssociatedFunctionDeclaration() : NULL; std::string fname = fdecl ? fdecl->get_qualified_name().getString() : ""; if (SageInterface::is_Java_language()) { if (0==fname.compare("System.getenv")) { found.push_back(fcall); CodeProperties::message(std::cout, fcall, "environment variable is read"); } } else if (0==fname.compare("::getenv")) { found.push_back(fcall); CodeProperties::message(std::cout, fcall, "environment variable is read"); } }
void ArrayAssignmentStatementTransformation::processArrayRefExp(SgVarRefExp* varRefExp, int dimension) { string variableName = varRefExp->get_symbol()->get_declaration()->get_name().str(); #if DEBUG cout << " Variable Name " << variableName << endl; #endif SgScopeStatement* scope = getScope(varRefExp); //SgVarRefExp* replaceVarRefExp = buildVarRefExp(variableName, getScope(varRefExp)); SgVarRefExp* newVarRefExp = buildVarRefExp("_" + variableName + "_pointer", scope); ROSE_ASSERT(newVarRefExp != NULL); string functionName = "SC_" + variableName; if (varRefExp->get_parent() != NULL) { SgFunctionCallExp* functionCallExpression = isSgFunctionCallExp(varRefExp->get_parent()->get_parent()); if (functionCallExpression != NULL) { string operatorName = TransformationSupport::getFunctionName(functionCallExpression); #if DEBUG cout << " Operator Name: " << operatorName << endl; #endif if (operatorName == "operator()") { // Create a copy since the original might be deleted during replacement SgExprListExp* functionExprList = isSgExprListExp(copyExpression(functionCallExpression->get_args())); substituteIndexes(functionExprList, scope); SgFunctionCallExp* functionCallExp = buildFunctionCallExp(functionName, buildIntType(), functionExprList, scope); SgPntrArrRefExp* pntrArrRefExp = buildPntrArrRefExp(newVarRefExp, functionCallExp); cout << " PntrArrayReference replacement: " << pntrArrRefExp->unparseToString() << endl; replaceExpression(functionCallExpression, pntrArrRefExp, false); } else { SgPntrArrRefExp* pntrRefExp = buildArrayRefExp(newVarRefExp, dimension, functionName, scope); replaceExpression(varRefExp, pntrRefExp); } } else { // Added to support simple cases like A = A+B where there is dependence SgPntrArrRefExp* pntrRefExp = buildArrayRefExp(newVarRefExp, dimension, functionName, scope); replaceExpression(varRefExp, pntrRefExp); } } }
/* * Replace the op_par_loop with respective kernel function */ void OPSource::fixParLoops(SgNode *n) { SgName kernel_name; SgFunctionCallExp *fn = isSgFunctionCallExp(n); if(fn != NULL) { string fn_name = fn->getAssociatedFunctionDeclaration()->get_name().getString(); if(fn_name.compare("op_par_loop_2")==0 || fn_name.compare("op_par_loop_3")==0 || fn_name.compare("op_par_loop_4")==0 || fn_name.compare("op_par_loop_5")==0 || fn_name.compare("op_par_loop_6")==0 || fn_name.compare("op_par_loop_7")==0 || fn_name.compare("op_par_loop_8")==0 || fn_name.compare("op_par_loop_9")==0) { SgExprListExp* exprList = fn->get_args(); SgExpressionPtrList &exprs = exprList->get_expressions(); SgFunctionRefExp* varExp = isSgFunctionRefExp(exprs[0]); if(varExp != NULL) { kernel_name = varExp->get_symbol()->get_name(); } exprs.erase(exprs.begin()); SgExpressionPtrList::iterator it = exprs.begin() + op_par_loop_args::num_params - 1; for(; it != exprs.end(); it += op_argument::num_params) { *it = buildCastExp( *it, buildPointerType(SgClassType::createType( buildStructDeclaration("op_dat<void>"))) ); } // Inject Name exprs.insert(exprs.begin(), buildStringVal(kernel_name)); // Fetch the declaration SgName name = SgName("op_par_loop_") + kernel_name; SgFunctionDeclaration *funcDecl = cudaFunctionDeclarations[kernel_name]; if(funcDecl) { SgFunctionRefExp* ref = isSgFunctionRefExp(fn->get_function()); SgFunctionSymbol *symbol = ref->get_symbol(); symbol->set_declaration(funcDecl); ref->set_symbol(symbol); fn->set_function(ref); } } } }
void visit(SgNode *n) { switch (n->variantT()) { case V_SgStatementExpression: reportError("GNU extension 'statement expression' is not allowed.", n); break; case V_SgFunctionCallExp: { SgFunctionCallExp *FCE = isSgFunctionCallExp(n); SgFunctionDeclaration *calleeFD = FCE->getAssociatedFunctionDeclaration(); if (!calleeFD) { reportError("calls through function pointers are not allowed.", n); } break; } default: break; } }
void evaluateAnalysisStates::visit(const Function& func, const DataflowNode& n, NodeState& state) { SgFunctionCallExp *fnCall = isSgFunctionCallExp(n.getNode()); if (!fnCall) return; if (!fnCall->getAssociatedFunctionSymbol()) return; string funcName = fnCall->getAssociatedFunctionSymbol()->get_name().getString(); if (funcName.find("testFunc") == string::npos) return; FiniteVarsExprsProductLattice *lat = dynamic_cast<FiniteVarsExprsProductLattice *>(state.getLatticeAbove(div)[0]); cout << indent << "Lattice before call to " << funcName << ": " << lat->str() << endl; set<varID> allVars = lat->getAllVars(); for (set<varID>::iterator i = allVars.begin(); i != allVars.end(); ++i) { string name = i->str(); cout << "Variable " << name << " "; if (expectations[funcName].find(name) == expectations[funcName].end()) { cout << "unspecified" << endl; continue; } Lattice *got = lat->getVarLattice(*i); ROSE_ASSERT(got); if (expectations[funcName][name] != got) { cout << "mismatched: " << got->str() << " was not the expected " << expectations[funcName][name].str(); numFails++; } else { cout << "matched"; numPass++; } cout << endl; } }
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; }
bool FortranAnalysis::matchRegionAssignment(SgExprStatement * expr_stmt) { SgBinaryOp * bin_op = isSgBinaryOp(expr_stmt->get_expression()); if (bin_op == NULL) return false; SgFunctionCallExp * fcall = isSgFunctionCallExp(bin_op->get_rhs_operand()); if (fcall == NULL) return false; SgFunctionRefExp * fref = isSgFunctionRefExp(fcall->get_function()); if (fref == NULL) return false; SgExpressionPtrList::iterator it = fcall->get_args()->get_expressions().begin(); std::string name = fref->get_symbol()->get_name().getString(); if (name == "interior" && it != fcall->get_args()->get_expressions().end()) { SgVarRefExp * var = isSgVarRefExp(*it); if (var == NULL) return false; AstTextAttribute * attr = (AstTextAttribute *) var->get_symbol()->getAttribute("dummy_attr"); if (attr == NULL) return false; if (attr->toString() != "DUMMY_ARRAY_ARG") return false; } return true; }
void PostProcessingTestFunctionCallArguments::visit (SgNode* node) { ROSE_ASSERT(node != NULL); #if 1 // DQ (4/26/2013): Debugging code ot chase down function call argument errors in the default expressions // constructed and the default arguments that we see in the final AST. SgFunctionCallExp* functionCallExpression = isSgFunctionCallExp(node); if (functionCallExpression != NULL) { printf ("================= Found SgFunctionCallExp \n"); SgExpressionPtrList & expList = functionCallExpression->get_args()->get_expressions(); SgExpressionPtrList::iterator i = expList.begin(); while (i != expList.end()) { printf ("################ function call argument expression = %p = %s \n",*i,(*i)->class_name().c_str()); (*i)->get_file_info()->display("function call argument expression"); i++; } } #endif }
void FunctionCallNormalization::visit( SgNode *astNode ) { SgStatement *stm = isSgStatement( astNode ); // visiting all statements which may contain function calls; // Note 1: we do not look at the body of loops, or sequences of statements, but only // at statements which may contain directly function calls; all other statements will have their component parts visited in turn if ( isSgEnumDeclaration( astNode ) || isSgVariableDeclaration( astNode ) || isSgVariableDefinition( astNode ) || isSgExprStatement( astNode ) || isSgForStatement( astNode ) || isSgReturnStmt( astNode ) || isSgSwitchStatement( astNode ) ) { // maintain the mappings from function calls to expressions (variables or dereferenced variables) map<SgFunctionCallExp *, SgExpression *> fct2Var; // list of Declaration structures, one structure per function call DeclarationPtrList declarations; bool variablesDefined = false; // list of function calls, in correnspondence with the inForTest list below list<SgNode*> functionCallExpList; list<bool> inForTest; SgForStatement *forStm = isSgForStatement( stm ); SgSwitchStatement *swStm = isSgSwitchStatement( stm ); list<SgNode*> temp1, temp2; // for-loops and Switch statements have conditions ( and increment ) expressed as expressions // and not as standalone statements; this will change in future Sage versions // TODO: when for-loops and switch statements have conditions expressed via SgStatements // these cases won't be treated separately; however, do-while will have condition expressed via expression // so that will be the only exceptional case to be treated separately if (forStm != NULL) { // create a list of function calls in the condition and increment expression // the order is important, the condition is evaluated after the increment expression // temp1 = FEOQueryForNodes( forStm->get_increment_expr_root(), V_SgFunctionCallExp ); // temp2 = FEOQueryForNodes( forStm->get_test_expr_root(), V_SgFunctionCallExp ); temp1 = FEOQueryForNodes( forStm->get_increment(), V_SgFunctionCallExp ); temp2 = FEOQueryForNodes( forStm->get_test_expr(), V_SgFunctionCallExp ); functionCallExpList = temp1; functionCallExpList.splice( functionCallExpList.end(), temp2 ); } else { if (swStm != NULL) { // create a list of function calls in the condition in the order of function evaluation // DQ (11/23/2005): Fixed SgSwitchStmt to have SgStatement for conditional. // list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector_root(), V_SgFunctionCallExp ); list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector(), V_SgFunctionCallExp ); functionCallExpList = temp1; } else { // create a list of function calls in the statement in the order of function evaluation functionCallExpList = FEOQueryForNodes( stm, V_SgFunctionCallExp ); } } // all function calls get replaced: this is because they can occur in expressions (e.g. for-loops) // which makes it difficult to build control flow graphs if ( functionCallExpList.size() > 0 ) { cout << "--------------------------------------\nStatement "; cout << stm->unparseToString() << "\n";; // traverse the list of function calls in the current statement, generate a structure Declaration for each call // put these structures in a list to be inserted in the code later for ( list<SgNode *>::iterator i = functionCallExpList.begin(); i != functionCallExpList.end(); i++ ) { variablesDefined = true; // get function call exp SgFunctionCallExp *exp = isSgFunctionCallExp( *i ); ROSE_ASSERT ( exp ); // get type of expression, generate unique variable name SgType *expType = exp->get_type(); ROSE_ASSERT ( expType ); Sg_File_Info *location = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); ROSE_ASSERT ( location ); ostringstream os; os << "__tempVar__" << location; SgName name = os.str().c_str(); // replace previous variable bindings in the AST SgExprListExp *paramsList = exp->get_args(); SgExpression *function = exp->get_function(); ROSE_ASSERT ( paramsList && function ); replaceFunctionCallsInExpression( paramsList, fct2Var ); replaceFunctionCallsInExpression( function, fct2Var ); // duplicate function call expression, for the initialization declaration and the assignment SgTreeCopy treeCopy; SgFunctionCallExp *newExpInit = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpInit ); SgFunctionCallExp *newExpAssign = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpAssign ); // variables Sg_File_Info *initLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *nonInitLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *assignLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); Declaration *newDecl = new Declaration(); SgStatement *nonInitVarDeclaration, *initVarDeclaration, *assignStmt; SgExpression *varRefExp; SgVariableSymbol *varSymbol; SgAssignOp *assignOp; SgInitializedName *initName; bool pointerTypeNeeded = false; // mark whether to replace inside or outside of ForStatement due to the // function call being inside the test or the increment for a for-loop statement // the 'inForTest' list is in 1:1 ordered correpondence with the 'declarations' list if ( forStm ) { // SgExpressionRoot // *testExp = isSgForStatement( astNode )->get_test_expr_root(), // *incrExp = isSgForStatement( astNode )->get_increment_expr_root(); SgExpression *testExp = isSgForStatement( astNode )->get_test_expr(), *incrExp = isSgForStatement( astNode )->get_increment(); SgNode *up = exp; while ( up && up != testExp && up != incrExp ) up = up->get_parent(); ROSE_ASSERT ( up ); // function call is in the condition of the for-loop if ( up == testExp ) inForTest.push_back( true ); // function call is in the increment expression else { inForTest.push_back( false ); // for increment expressions we need to be able to reassign the return value // of the function; if the ret value is a reference, we need to generate a // pointer of that type (to be able to reassign it later) if ( isSgReferenceType( expType ) ) pointerTypeNeeded = true; } } // for do-while statements: we need to generate declaration of type pointer to be able to have // non-assigned references when looping and assign them at the end of the body of the loop if ( isSgDoWhileStmt( stm->get_parent() ) && isSgReferenceType( expType ) ) pointerTypeNeeded = true; // we have a function call returning a reference and we can't initialize the variable // at the point of declaration; we need to define the variable as a pointer if ( pointerTypeNeeded ) { // create 'address of' term for function expression, so we can assign it to the pointer SgAddressOfOp *addressOp = new SgAddressOfOp( assignLoc, newExpAssign, expType ); // create noninitialized declaration SgType *base = isSgReferenceType( expType )->get_base_type(); ROSE_ASSERT( base ); SgPointerType *ptrType = SgPointerType::createType( isSgReferenceType( expType )->get_base_type() ); ROSE_ASSERT ( ptrType ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, ptrType ); // create assignment (symbol, varRefExp, assignment) initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); varRefExp = new SgVarRefExp( assignLoc, varSymbol ); SgPointerDerefExp *ptrDeref= new SgPointerDerefExp( assignLoc, varRefExp, expType ); ROSE_ASSERT ( isSgExpression( varRefExp ) && ptrDeref ); assignOp = new SgAssignOp( assignLoc, varRefExp, addressOp, ptrType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt && nonInitVarDeclaration ); // we don't need initialized declarations in this case initVarDeclaration = NULL; // save new mapping fct2Var.insert( Fct2Var( exp, ptrDeref ) ); } else { // create (non- &)initialized declarations, initialized name & symbol SgAssignInitializer *declInit = new SgAssignInitializer( initLoc, newExpInit, expType ); ROSE_ASSERT ( declInit ); initVarDeclaration = new SgVariableDeclaration ( initLoc, name, expType, declInit ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, expType ); ROSE_ASSERT ( initVarDeclaration && nonInitVarDeclaration ); initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); newExpInit->set_parent( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); // create variable ref exp varRefExp = new SgVarRefExp( assignLoc, varSymbol ); ROSE_ASSERT ( isSgVarRefExp( varRefExp ) ); // create the assignment assignOp = new SgAssignOp( assignLoc, varRefExp, newExpAssign, expType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt ); initVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( initVarDeclaration )->set_definingDeclaration( isSgDeclarationStatement( initVarDeclaration ) ); // save new mapping fct2Var.insert( Fct2Var( exp, varRefExp ) ); } // save the 'declaration' structure, with all 3 statements and the variable name newDecl->nonInitVarDeclaration = nonInitVarDeclaration; newDecl->initVarDeclaration = initVarDeclaration; newDecl->assignment = assignStmt; newDecl->name = name; nonInitVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( nonInitVarDeclaration )->set_definingDeclaration( isSgVariableDeclaration( nonInitVarDeclaration ) ); assignStmt->set_parent( stm->get_parent() ); declarations.push_back( newDecl ); } // end for } // end if fct calls in crt stmt > 1 SgScopeStatement *scope = stm->get_scope(); ROSE_ASSERT ( scope ); // insert function bindings to variables; each 'declaration' structure in the list // corresponds to one function call for ( DeclarationPtrList::iterator i = declarations.begin(); i != declarations.end(); i++ ) { Declaration *d = *i; ROSE_ASSERT ( d && d->assignment && d->nonInitVarDeclaration ); // if the current statement is a for-loop, we insert Declarations before & in the loop body, depending on the case if ( forStm ) { SgStatement *parentScope = isSgStatement( stm->get_scope() ); SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfFor(forStm); ROSE_ASSERT ( !inForTest.empty() && body && parentScope ); // SgStatementPtrList &list = body->get_statements(); // if function call is in loop condition, we add initialized variable before the loop and at its end // hoist initialized variable declarations outside the loop if ( inForTest.front() ) { ROSE_ASSERT ( d->initVarDeclaration ); parentScope->insert_statement( stm, d->initVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // function call is in loop post increment so add noninitialized variable decls above the loop else { parentScope->insert_statement( stm, d->nonInitVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // in a for-loop, always insert assignments at the end of the loop body->get_statements().push_back( d->assignment ); d->assignment->set_parent( body ); // remove marker inForTest.pop_front(); } else { // look at the type of the enclosing scope switch ( scope->variantT() ) { // while stmts have to repeat the function calls at the end of the loop; // note there is no "break" statement, since we want to also add initialized // declarations before the while-loop case V_SgWhileStmt: { // assignments need to be inserted at the end of each while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfWhile(isSgWhileStmt( scope ) ); ROSE_ASSERT ( body ); d->assignment->set_parent( body ); body->get_statements().push_back( d->assignment ); } // SgForInitStatement has scope SgForStatement, move declarations before the for loop; // same thing if the enclosing scope is an If, or Switch statement case V_SgForStatement: case V_SgIfStmt: case V_SgSwitchStatement: { // adding bindings (initialized variable declarations only, not assignments) // outside the statement, in the parent scope SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->initVarDeclaration, true );\ // setting the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } break; // do-while needs noninitialized declarations before the loop, with assignments inside the loop case V_SgDoWhileStmt: { // adding noninitialized variable declarations before the body of the loop SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->nonInitVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); // adding assignemts at the end of the do-while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfDoWhile( isSgDoWhileStmt(scope) ); ROSE_ASSERT ( body ); body->get_statements().push_back( d->assignment ); d->assignment->set_parent(body); } break; // for all other scopes, add bindings ( initialized declarations ) before the statement, in the same scope default: scope->insert_statement( stm, d->initVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } } } // once we have inserted all variable declarations, we need to replace top-level calls in the original statement if ( variablesDefined ) { cout << "\tReplacing in the expression " << stm->unparseToString() << "\n"; // for ForStatements, replace expressions in condition and increment expressions, // not in the body, since those get replace later if ( forStm ) { // SgExpressionRoot *testExp = forStm->get_test_expr_root(), *incrExp = forStm->get_increment_expr_root(); SgExpression *testExp = forStm->get_test_expr(), *incrExp = forStm->get_increment(); replaceFunctionCallsInExpression( incrExp, fct2Var ); replaceFunctionCallsInExpression( testExp, fct2Var ); } else if ( swStm ) { // DQ (11/23/2005): Fixed SgSwitch to permit use of declaration for conditional // replaceFunctionCallsInExpression( swStm->get_item_selector_root(), fct2Var ); replaceFunctionCallsInExpression( swStm->get_item_selector(), fct2Var ); } else replaceFunctionCallsInExpression( stm, fct2Var ); } } // end if isSgStatement block }
StencilEvaluation_InheritedAttribute StencilEvaluationTraversal::evaluateInheritedAttribute (SgNode* astNode, StencilEvaluation_InheritedAttribute inheritedAttribute ) { #if 0 printf ("In evaluateInheritedAttribute(): astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif bool foundPairShiftDoubleConstructor = false; // This is for stencil specifications using vectors of points to represent offsets (not finished). // bool foundVariableDeclarationForStencilInput = false; double stencilCoeficientValue = 0.0; // StencilOffsetFSM offset; StencilOffsetFSM* stencilOffsetFSM = NULL; // We want to interogate the SgAssignInitializer, but we need to generality in the refactored function to use any SgInitializer (e.g. SgConstructorInitializer, etc.). SgInitializedName* initializedName = detectVariableDeclarationOfSpecificType (astNode,"Point"); if (initializedName != NULL) { // This is the code that is specific to the DSL (e.g. the semantics of getZeros() and getUnitv() functions). // So this may be the limit of what can be refactored to common DSL support code. // Or I can maybe do a second pass at atempting to refactor more code later. string name = initializedName->get_name(); SgInitializer* initializer = initializedName->get_initptr(); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); if (assignInitializer != NULL) { SgExpression* exp = assignInitializer->get_operand(); ROSE_ASSERT(exp != NULL); SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(exp); if (functionCallExp != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); string functionName = functionSymbol->get_name(); #if 0 printf ("functionName = %s \n",functionName.c_str()); #endif if (functionName == "getZeros") { // We leverage the semantics of known functions used to initialize "Point" objects ("getZeros" initialized the Point object to be all zeros). // In a stencil this will be the center point from which all other points will have non-zero offsets. // For a common centered difference discretization this will be the center point of the stencil. #if 0 printf ("Identified and interpreting the semantics of getZeros() function \n"); #endif stencilOffsetFSM = new StencilOffsetFSM(0,0,0); ROSE_ASSERT(stencilOffsetFSM != NULL); } if (functionName == "getUnitv") { // We leverage the semantics of known functions used to initialize "Point" objects // ("getUnitv" initializes the Point object to be a unit vector for a specific input dimention). // In a stencil this will be an ofset from the center point. #if 0 printf ("Identified and interpreting the semantics of getUnitv() function \n"); #endif // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); // ROSE_ASSERT(intVal != NULL); if (intVal != NULL) { int value = intVal->get_value(); #if 0 printf ("value = %d \n",value); #endif switch(value) { case 0: stencilOffsetFSM = new StencilOffsetFSM(1,0,0); break; case 1: stencilOffsetFSM = new StencilOffsetFSM(0,1,0); break; case 2: stencilOffsetFSM = new StencilOffsetFSM(0,0,1); break; default: { printf ("Error: default reached in switch: value = %d (for be value of 0, 1, or 2) \n",value); ROSE_ASSERT(false); } } ROSE_ASSERT(stencilOffsetFSM != NULL); // End of test for intVal != NULL } else { #if 0 printf ("functionArg = %p = %s \n",functionArg,functionArg->class_name().c_str()); #endif } } // ROSE_ASSERT(stencilOffsetFSM != NULL); } } } if (stencilOffsetFSM != NULL) { // Put the FSM into the map. #if 0 printf ("Put the stencilOffsetFSM = %p into the StencilOffsetMap using key = %s \n",stencilOffsetFSM,name.c_str()); #endif ROSE_ASSERT(StencilOffsetMap.find(name) == StencilOffsetMap.end()); // We have a choice of syntax to add the element to the map. // StencilOffsetMap.insert(pair<string,StencilOffsetFSM*>(name,stencilOffsetFSM)); StencilOffsetMap[name] = stencilOffsetFSM; } // new StencilOffsetFSM(); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Recognize member function calls on "Point" objects so that we can trigger events on those associated finite state machines. bool isTemplateClass = false; bool isTemplateFunctionInstantiation = false; SgInitializedName* initializedNameUsedToCallMemberFunction = NULL; SgFunctionCallExp* functionCallExp = detectMemberFunctionOfSpecificClassType(astNode,initializedNameUsedToCallMemberFunction,"Point",isTemplateClass,"operator*=",isTemplateFunctionInstantiation); if (functionCallExp != NULL) { // This is the DSL specific part (capturing the semantics of operator*= with specific integer values). // The name of the variable off of which the member function is called (variable has type "Point"). ROSE_ASSERT(initializedNameUsedToCallMemberFunction != NULL); string name = initializedNameUsedToCallMemberFunction->get_name(); // Need to get the dimention argument. SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // This function has a single argument. ROSE_ASSERT(argumentList->get_expressions().size() == 1); SgExpression* functionArg = argumentList->get_expressions()[0]; ROSE_ASSERT(functionArg != NULL); SgIntVal* intVal = isSgIntVal(functionArg); bool usingUnaryMinus = false; if (intVal == NULL) { SgMinusOp* minusOp = isSgMinusOp(functionArg); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; intVal = isSgIntVal(minusOp->get_operand()); } } ROSE_ASSERT(intVal != NULL); int value = intVal->get_value(); if (usingUnaryMinus == true) { value *= -1; } #if 0 printf ("value = %d \n",value); #endif // Look up the stencil offset finite state machine ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 stencilOffsetFSM->display("before multiply event"); #endif if (value == -1) { // Execute the event on the finte state machine to accumulate the state. stencilOffsetFSM->operator*=(-1); } else { printf ("Error: constant value other than -1 are not supported \n"); ROSE_ASSERT(false); } #if 0 stencilOffsetFSM->display("after multiply event"); #endif } // Detection of "pair<Shift,double>(xdir,ident)" defined as an event in the stencil finite machine model. // Actually, it is the Stencil that is create using the "pair<Shift,double>(xdir,ident)" that should be the // event so we first detect the SgConstructorInitializer. There is not other code similar to this which // has to test for the template arguments, so this has not yet refactored into the dslSupport.C file. // I will do this later since this is general support that could be resused in other DSL compilers. SgConstructorInitializer* constructorInitializer = isSgConstructorInitializer(astNode); if (constructorInitializer != NULL) { // DQ (10/20/2014): This can sometimes be NULL. // ROSE_ASSERT(constructorInitializer->get_class_decl() != NULL); SgClassDeclaration* classDeclaration = constructorInitializer->get_class_decl(); // ROSE_ASSERT(classDeclaration != NULL); if (classDeclaration != NULL) { #if 0 printf ("constructorInitializer = %p class name = %s \n",constructorInitializer,classDeclaration->get_name().str()); #endif SgTemplateInstantiationDecl* templateInstantiationDecl = isSgTemplateInstantiationDecl(classDeclaration); // ROSE_ASSERT(templateInstantiationDecl != NULL); #if 0 if (templateInstantiationDecl != NULL) { printf ("constructorInitializer = %p name = %s template name = %s \n",constructorInitializer,templateInstantiationDecl->get_name().str(),templateInstantiationDecl->get_templateName().str()); } #endif // if (classDeclaration->get_name() == "pair") if (templateInstantiationDecl != NULL && templateInstantiationDecl->get_templateName() == "pair") { // Look at the template parameters. #if 0 printf ("Found template instantiation for pair \n"); #endif SgTemplateArgumentPtrList & templateArgs = templateInstantiationDecl->get_templateArguments(); if (templateArgs.size() == 2) { // Now look at the template arguments and check that they represent the pattern that we are looking for in the AST. // It is not clear now flexible we should be, at present shift/coeficent pairs must be specified exactly one way. SgType* type_0 = templateArgs[0]->get_type(); SgType* type_1 = templateArgs[1]->get_type(); if ( type_0 != NULL && type_1 != NULL) { SgClassType* classType_0 = isSgClassType(type_0); // ROSE_ASSERT(classType_0 != NULL); if (classType_0 != NULL) { SgClassDeclaration* classDeclarationType_0 = isSgClassDeclaration(classType_0->get_declaration()); ROSE_ASSERT(classDeclarationType_0 != NULL); #if 0 printf ("templateArgs[0]->get_name() = %s \n",classDeclarationType_0->get_name().str()); printf ("templateArgs[1]->get_type()->class_name() = %s \n",type_1->class_name().c_str()); #endif bool foundShiftExpression = false; bool foundStencilCoeficient = false; // We might want to be more flexiable about the type of the 2nd parameter (allow SgTypeFloat, SgTypeComplex, etc.). if (classDeclarationType_0->get_name() == "Shift" && type_1->variant() == V_SgTypeDouble) { // Found a pair<Shift,double> input for a stencil. #if 0 printf ("##### Found a pair<Shift,double>() input for a stencil input \n"); #endif // ***************************************************************************************************** // Look at the first parameter to the pair<Shift,double>() constructor. // ***************************************************************************************************** SgExpression* stencilOffset = constructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(stencilOffset != NULL); #if 0 printf ("stencilOffset = %p = %s \n",stencilOffset,stencilOffset->class_name().c_str()); #endif SgConstructorInitializer* stencilOffsetConstructorInitializer = isSgConstructorInitializer(stencilOffset); if (stencilOffsetConstructorInitializer != NULL) { // This is the case of a Shift being constructed implicitly from a Point (doing so more directly would be easier to make sense of in the AST). #if 0 printf ("!!!!! Looking for the stencil offset \n"); #endif ROSE_ASSERT(stencilOffsetConstructorInitializer->get_class_decl() != NULL); SgClassDeclaration* stencilOffsetClassDeclaration = stencilOffsetConstructorInitializer->get_class_decl(); ROSE_ASSERT(stencilOffsetClassDeclaration != NULL); #if 0 printf ("stencilOffsetConstructorInitializer = %p class name = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration->get_name().str()); printf ("stencilOffsetConstructorInitializer = %p class = %p = %s \n",stencilOffsetConstructorInitializer,stencilOffsetClassDeclaration,stencilOffsetClassDeclaration->class_name().c_str()); #endif // This should not be a template instantiation (the Shift is defined to be a noo-template class declaration, not a template class declaration). SgTemplateInstantiationDecl* stencilOffsetTemplateInstantiationDecl = isSgTemplateInstantiationDecl(stencilOffsetClassDeclaration); ROSE_ASSERT(stencilOffsetTemplateInstantiationDecl == NULL); if (stencilOffsetClassDeclaration != NULL && stencilOffsetClassDeclaration->get_name() == "Shift") { // Now we know that the type associated with the first template parameter is associated with the class "Shift". // But we need so also now what the first parametr is associate with the constructor initializer, since it will // be the name of the variable used to interprete the stencil offset (and the name of the variable will be the // key into the map of finite machine models used to accumulate the state of the stencil offsets that we accumulate // to build the stencil. // Now we need the value of the input (computed using it's fine state machine). SgExpression* inputToShiftConstructor = stencilOffsetConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToShiftConstructor != NULL); SgConstructorInitializer* inputToShiftConstructorInitializer = isSgConstructorInitializer(inputToShiftConstructor); if (stencilOffsetConstructorInitializer != NULL) { SgExpression* inputToPointConstructor = inputToShiftConstructorInitializer->get_args()->get_expressions()[0]; ROSE_ASSERT(inputToPointConstructor != NULL); // This should be a SgVarRefExp (if we strictly follow the stencil specification rules (which are not written down yet). SgVarRefExp* inputToPointVarRefExp = isSgVarRefExp(inputToPointConstructor); if (inputToPointVarRefExp != NULL) { #if 0 printf ("Found varRefExp in bottom of chain of constructors \n"); #endif SgVariableSymbol* variableSymbolForOffset = isSgVariableSymbol(inputToPointVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForOffset != NULL); SgInitializedName* initializedNameForOffset = variableSymbolForOffset->get_declaration(); ROSE_ASSERT(initializedNameForOffset != NULL); SgInitializer* initializer = initializedNameForOffset->get_initptr(); ROSE_ASSERT(initializer != NULL); #if 0 printf ("Found initializedName: name = %s in bottom of chain of constructors: initializer = %p = %s \n",initializedNameForOffset->get_name().str(),initializer,initializer->class_name().c_str()); #endif // Record the name to be used as a key into the map of "StencilOffset" finite state machines. SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); string name = initializedNameForOffset->get_name(); // Look up the current state in the finite state machine for the "Point". // Check that this is a previously defined stencil offset. ROSE_ASSERT(StencilOffsetMap.find(name) != StencilOffsetMap.end()); // StencilOffsetFSM* stencilOffsetFSM = StencilOffsetMap[name]; stencilOffsetFSM = StencilOffsetMap[name]; ROSE_ASSERT(stencilOffsetFSM != NULL); #if 0 printf ("We have found the StencilOffsetFSM associated with the StencilOffset named %s \n",name.c_str()); #endif #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { printf ("What is this expression: inputToPointConstructor = %p = %s \n",inputToPointConstructor,inputToPointConstructor->class_name().c_str()); ROSE_ASSERT(false); } } #if 0 printf ("Found Shift type \n"); #endif foundShiftExpression = true; } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { // This case for the specification of a Shift in the first argument is not yet supported (need an example of this). printf ("This case of using a shift is not a part of what is supported \n"); } // ***************************************************************************************************** // Look at the second parameter to the pair<Shift,double>(first_parameter,second_parameter) constructor. // ***************************************************************************************************** SgExpression* stencilCoeficent = constructorInitializer->get_args()->get_expressions()[1]; ROSE_ASSERT(stencilCoeficent != NULL); SgVarRefExp* stencilCoeficentVarRefExp = isSgVarRefExp(stencilCoeficent); if (stencilCoeficentVarRefExp != NULL) { // Handle the case where this is a constant SgVarRefExp and the value is available in the declaration. SgVariableSymbol* variableSymbolForConstant = isSgVariableSymbol(stencilCoeficentVarRefExp->get_symbol()); ROSE_ASSERT(variableSymbolForConstant != NULL); SgInitializedName* initializedNameForConstant = variableSymbolForConstant->get_declaration(); ROSE_ASSERT(initializedNameForConstant != NULL); SgInitializer* initializer = initializedNameForConstant->get_initptr(); ROSE_ASSERT(initializer != NULL); SgAssignInitializer* assignInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignInitializer != NULL); SgValueExp* valueExp = isSgValueExp(assignInitializer->get_operand()); bool usingUnaryMinus = false; // ROSE_ASSERT(valueExp != NULL); if (valueExp == NULL) { SgExpression* operand = assignInitializer->get_operand(); SgMinusOp* minusOp = isSgMinusOp(operand); if (minusOp != NULL) { #if 0 printf ("Using SgMinusOp on stencil constant \n"); #endif usingUnaryMinus = true; valueExp = isSgValueExp(minusOp->get_operand()); } } SgDoubleVal* doubleVal = isSgDoubleVal(valueExp); // ROSE_ASSERT(doubleVal != NULL); double value = 0.0; if (doubleVal == NULL) { // Call JP's function to evaluate the constant expression. ROSE_ASSERT(valueExp == NULL); ROSE_ASSERT(stencilCoeficent != NULL); DSL_Support::const_numeric_expr_t const_expression = DSL_Support::evaluateConstNumericExpression(stencilCoeficent); if (const_expression.hasValue_ == true) { ROSE_ASSERT(const_expression.isIntOnly_ == false); value = const_expression.value_; printf ("const expression evaluated to value = %4.2f \n",value); } else { printf ("constnat value expression could not be evaluated to a constant \n"); ROSE_ASSERT(false); } } else { #if 1 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif value = (usingUnaryMinus == false) ? doubleVal->get_value() : -(doubleVal->get_value()); } #if 1 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { // When we turn on constant folding in the frontend we eveluate directly to a SgDoubleVal. SgDoubleVal* doubleVal = isSgDoubleVal(stencilCoeficent); if (doubleVal != NULL) { ROSE_ASSERT(doubleVal != NULL); #if 0 printf ("SgDoubleVal value = %f \n",doubleVal->get_value()); #endif double value = doubleVal->get_value(); #if 0 printf ("Stencil coeficient = %f \n",value); #endif foundStencilCoeficient = true; stencilCoeficientValue = value; } else { printf ("Error: second parameter in pair for stencil is not a SgVarRefExp (might be explicit value not yet supported) \n"); printf (" --- stencilCoeficent = %p = %s \n",stencilCoeficent,stencilCoeficent->class_name().c_str()); ROSE_ASSERT(false); } } } #if 0 printf ("foundShiftExpression = %s \n",foundShiftExpression ? "true" : "false"); printf ("foundStencilCoeficient = %s \n",foundStencilCoeficient ? "true" : "false"); #endif if (foundShiftExpression == true && foundStencilCoeficient == true) { #if 0 printf ("Found pair<Shift,double>() constructor expression! \n"); #endif foundPairShiftDoubleConstructor = true; } // End of test for classType_0 != NULL } } } } else { #if 0 printf ("This is not a SgConstructorInitializer for the pair templated class \n"); #endif } // End of test for classDeclaration != NULL } } #if 0 printf ("foundPairShiftDoubleConstructor = %s \n",foundPairShiftDoubleConstructor ? "true" : "false"); #endif if (foundPairShiftDoubleConstructor == true) { // This is the recognition of an event for one of the finite state machines we implement to evaluate the stencil at compile time. #if 0 printf ("In evaluateInheritedAttribute(): found pair<Shift,double>() constructor expression! \n"); printf (" --- stencilOffsetFSM = %p \n",stencilOffsetFSM); printf (" --- stencilCoeficientValue = %f \n",stencilCoeficientValue); #endif ROSE_ASSERT(stencilOffsetFSM != NULL); inheritedAttribute.stencilOffsetFSM = stencilOffsetFSM; inheritedAttribute.stencilCoeficientValue = stencilCoeficientValue; #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } // Construct the return attribute from the modified input attribute. return StencilEvaluation_InheritedAttribute(inheritedAttribute); }
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); }
void FortranProgramDeclarationsAndDefinitions::visit (SgNode * node) { using boost::filesystem::path; using boost::filesystem::system_complete; using boost::iequals; using boost::starts_with; using boost::lexical_cast; using std::string; if (isSgSourceFile (node)) { path p = system_complete (path (isSgSourceFile (node)->getFileName ())); currentSourceFile = p.filename (); Debug::getInstance ()->debugMessage ("Source file '" + currentSourceFile + "' detected", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__ ); } else if (Globals::getInstance ()->isInputFile (currentSourceFile)) { /* * ====================================================== * Only process this portion of the AST if we recognise * this source file as one passed on the command line. In * Fortran, .rmod files are sometimes generated whose * traversal should be avoided * ====================================================== */ switch (node->variantT ()) { case V_SgModuleStatement: { SgModuleStatement * moduleStatement = isSgModuleStatement (node); currentModuleName = moduleStatement->get_name ().getString (); fileNameToModuleNames[currentSourceFile].push_back (currentModuleName); moduleNameToFileName[currentModuleName] = currentSourceFile; Debug::getInstance ()->debugMessage ("Module '" + currentModuleName + "' in file '" + currentSourceFile + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__ ); break; } case V_SgProcedureHeaderStatement: { /* * ====================================================== * We need to store all subroutine definitions since we * later have to copy and modify the user kernel subroutine * ====================================================== */ SgProcedureHeaderStatement * procedureHeaderStatement = isSgProcedureHeaderStatement (node); string const subroutineName = procedureHeaderStatement->get_name ().getString (); subroutinesInSourceCode[subroutineName] = procedureHeaderStatement; ROSE_ASSERT (currentModuleName.size() > 0); moduleNameToSubroutines[currentModuleName].push_back (subroutineName); subroutineToFileName[subroutineName] = currentSourceFile; Debug::getInstance ()->debugMessage ( "Found procedure header statement '" + procedureHeaderStatement->get_name ().getString () + "' in file '" + currentSourceFile + "', and module '" + currentModuleName + "'", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); break; } case V_SgFunctionCallExp: { /* * ====================================================== * Function call found in the AST. Get its actual arguments * and the callee name * ====================================================== */ SgFunctionCallExp * functionCallExp = isSgFunctionCallExp (node); SgExprListExp * actualArguments = functionCallExp->get_args (); string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call '" + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); if ( iequals (calleeName, OP2::OP_DECL_SET) || iequals (calleeName, OP2::OP_DECL_SET_HDF5) ) { /* * ====================================================== * An OP_SET variable declared through an OP_DECL_SET call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_SET_HDF5) ) isHDF5Format = true; FortranOpSetDefinition * opSetDeclaration = new FortranOpSetDefinition (actualArguments, isHDF5Format); OpSetDefinitions[opSetDeclaration->getVariableName ()] = opSetDeclaration; } else if ( iequals (calleeName, OP2::OP_DECL_MAP) || iequals (calleeName, OP2::OP_DECL_MAP_HDF5) ) { /* * ====================================================== * An OP_MAP variable declared through an OP_DECL_MAP call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_MAP_HDF5) ) { isHDF5Format = true; Debug::getInstance ()->debugMessage ("This is the HDF5 version: '" + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } FortranOpMapDefinition * opMapDeclaration = new FortranOpMapDefinition (actualArguments, isHDF5Format); OpMapDefinitions[opMapDeclaration->getVariableName ()] = opMapDeclaration; } else if ( iequals (calleeName, OP2::OP_DECL_DAT) || iequals (calleeName, OP2::OP_DECL_DAT_HDF5) ) { /* * ====================================================== * An OP_DAT variable declared through an OP_DECL_DAT call * ====================================================== */ bool isHDF5Format = false; if ( iequals (calleeName, OP2::OP_DECL_DAT_HDF5) ) isHDF5Format = true; FortranOpDatDefinition * opDatDeclaration = new FortranOpDatDefinition (actualArguments, isHDF5Format); OpDatDefinitions[opDatDeclaration->getVariableName ()] = opDatDeclaration; } else if (iequals (calleeName, OP2::OP_DECL_CONST)) { /* * ====================================================== * A constant declared through an OP_DECL_CONST call * ====================================================== */ FortranOpConstDefinition * opConstDeclaration = new FortranOpConstDefinition (actualArguments, functionCallExp); OpConstDefinitions[opConstDeclaration->getVariableName ()] = opConstDeclaration; } else if (starts_with (calleeName, OP2::OP_PAR_LOOP)) { /* * ====================================================== * The first argument to an 'OP_PAR_LOOP' call should be * a reference to the kernel function. Cast it and proceed, * otherwise throw an exception * ====================================================== */ SgExprListExp * actualArguments = functionCallExp->get_args (); SgFunctionRefExp * functionRefExpression = isSgFunctionRefExp ( actualArguments->get_expressions ().front ()); ROSE_ASSERT (functionRefExpression != NULL); string const userSubroutineName = functionRefExpression->getAssociatedFunctionDeclaration ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found '" + calleeName + "' with (host) user subroutine '" + userSubroutineName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); if (parallelLoops.find (userSubroutineName) == parallelLoops.end ()) { int numberOfOpArgs = getLoopSuffixNumber ( calleeName ); /* * ====================================================== * If this kernel has not been previously encountered then * build a new parallel loop representation * ====================================================== */ FortranParallelLoop * parallelLoop = new FortranParallelLoop ( functionCallExp); parallelLoop->addFileName (currentSourceFile); parallelLoops[userSubroutineName] = parallelLoop; Debug::getInstance ()->debugMessage ("Parallel loop with '" + lexical_cast <string> (numberOfOpArgs) + "' arguments", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); analyseParallelLoopArguments (parallelLoop, actualArguments, numberOfOpArgs); parallelLoop->checkArguments (); parallelLoop->setIncrementalID (IDCounter); IDCounter++; } else { Debug::getInstance ()->debugMessage ("Parallel loop for '" + userSubroutineName + "' already created", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); ParallelLoop * parallelLoop = parallelLoops[userSubroutineName]; parallelLoop->addFunctionCallExpression (functionCallExp); parallelLoop->addFileName (currentSourceFile); } } break; } default: { break; } } } }
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; } } }
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); } } } } }
void SimpleInstrumentation::visit ( SgNode* astNode ) { switch(astNode->variantT()) { case V_SgFunctionCallExp: { SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(astNode); SgExpression *function = functionCallExp->get_function(); ROSE_ASSERT(function); switch (function->variantT()) { case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(function); SgFunctionSymbol *symbol = functionRefExp->get_symbol(); ROSE_ASSERT(symbol != NULL); SgFunctionDeclaration *functionDeclaration = symbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); if (symbol == functionSymbol) { // Now we know that we have found the correct function call // (even in the presence of overloading or other forms of hidding) // Now fixup the symbol and type of the SgFunctionRefExp object to // reflect the new function to be called (after this we still have to // fixup the argument list in the SgFunctionCallExp. // We only want to build the decalration once (and insert it into the global scope) // after that we save the symbol and reuse it. if (newFunctionSymbol == NULL) { SgFunctionType* originalFunctionType = isSgFunctionType(functionSymbol->get_type()); ROSE_ASSERT(originalFunctionType != NULL); newFunctionSymbol = buildNewFunctionDeclaration (TransformationSupport::getStatement(astNode),originalFunctionType); } ROSE_ASSERT(newFunctionSymbol != NULL); ROSE_ASSERT(newFunctionSymbol->get_type() != NULL); functionRefExp->set_symbol(newFunctionSymbol); } break; } default: cerr<<"warning: unrecognized variant: "<<function->class_name(); } break; } case V_SgFunctionDeclaration: { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); string functionName = functionDeclaration->get_name().str(); if (functionName == "send") { SgFunctionType *functionType = functionDeclaration->get_type(); ROSE_ASSERT(functionType != NULL); bool foundFunction = false; if (functionType->get_return_type()->unparseToString() == "ssize_t") { SgTypePtrList & argumentList = functionType->get_arguments(); SgTypePtrList::iterator i = argumentList.begin(); if ( (*i++)->unparseToString() == "int" ) if ( (*i++)->unparseToString() == "const void *" ) if ( (*i++)->unparseToString() == "size_t" ) if ( (*i++)->unparseToString() == "int" ) foundFunction = true; } if (foundFunction == true) { // Now get the sysmbol using functionType SgScopeStatement *scope = functionDeclaration->get_scope(); ROSE_ASSERT(scope != NULL); functionSymbol = scope->lookup_function_symbol (functionName,functionType); } } break; } default: { // No other special cases } } }
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; }
int main(int argc, char **argv) { SgProject *project = frontend(argc, argv); // Instantiate a class hierarchy wrapper. ClassHierarchyWrapper classHierarchy( project ); #if 0 std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project, V_SgVariableDefinition); for (std::list<SgNode *>::iterator it = nodes2.begin(); it != nodes2.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDefinition *varDefn = isSgVariableDefinition(n); ROSE_ASSERT(varDefn != NULL); std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl; } std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project, V_SgVariableDeclaration); for (std::list<SgNode *>::iterator it = nodes1.begin(); it != nodes1.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDeclaration *varDecl = isSgVariableDeclaration(n); ROSE_ASSERT(varDecl != NULL); SgInitializedNamePtrList &variables = varDecl->get_variables(); SgInitializedNamePtrList::iterator varIter; for (varIter = variables.begin(); varIter != variables.end(); ++varIter) { SgNode *var = *varIter; ROSE_ASSERT(var != NULL); SgInitializedName *initName = isSgInitializedName(var); ROSE_ASSERT(initName != NULL); if ( isSgClassType(initName->get_type()) ) { SgClassType *classType = isSgClassType(initName->get_type()); ROSE_ASSERT(classType != NULL); SgDeclarationStatement *declStmt = classType->get_declaration(); ROSE_ASSERT(declStmt != NULL); SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt); ROSE_ASSERT(classDeclaration != NULL); // std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl; SgClassDefinition *classDefinition = classDeclaration->get_definition(); if ( classDefinition != NULL ) { std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl; } } } } std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDeclaration); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDeclaration *classDeclaration1 = isSgClassDeclaration(n); ROSE_ASSERT(classDeclaration1 != NULL); SgDeclarationStatement *definingDecl = classDeclaration1->get_definingDeclaration(); if ( definingDecl == NULL ) continue; SgClassDeclaration *classDeclaration = isSgClassDeclaration(definingDecl); ROSE_ASSERT(classDeclaration != NULL); SgClassDefinition *classDefinition = classDeclaration->get_definition(); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #endif #if 1 #if 0 std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDefinition); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDefinition *classDefinition = isSgClassDefinition(n); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #else // Collect all function/method invocations. std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgFunctionCallExp); unsigned int numCallSites = 0; unsigned int numMonomorphicCallSites = 0; unsigned int numPossibleResolutions = 0; // Visit each call site. for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(n); ROSE_ASSERT(functionCallExp != NULL); // We are only interested in examining method invocations. bool isDotExp = false; bool isLhsRefOrPtr = false; // std::cout << "method?: " << functionCallExp->unparseToCompleteString() << std::endl; if ( !isMethodCall(functionCallExp, isDotExp, isLhsRefOrPtr) ) continue; // std::cout << "method: " << functionCallExp->unparseToCompleteString() << std::endl; numCallSites++; if ( isDotExp && !isLhsRefOrPtr ) { // If this is a dot expression (i.e., a.foo()), we can // statically determine its type-- unless the left-hand // side is a reference type. numMonomorphicCallSites++; numPossibleResolutions++; // std::cout << "dot: " << functionCallExp->unparseToCompleteString() << std::endl; continue; } // std::cout << "methodPtr: " << functionCallExp->unparseToCompleteString() << std::endl; // Retrieve the static function declaration. SgFunctionDeclaration *functionDeclaration = getFunctionDeclaration(functionCallExp); // Ensure it is actually a method declaration. SgMemberFunctionDeclaration *memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration); ROSE_ASSERT(memberFunctionDeclaration != NULL); unsigned int numResolutionsForMethod = 0; // Certainly can be resolved to the static method (unless it // is pure virtual). if ( !isPureVirtual(memberFunctionDeclaration) ) { numResolutionsForMethod++; } #if 0 if ( ( isVirtual(functionDeclaration) ) || ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) { #else if ( isVirtual(functionDeclaration) ) { #endif // std::cout << "tracking: " << functionDeclaration->unparseToString() << std::endl; SgClassDefinition *classDefinition = isSgClassDefinition(memberFunctionDeclaration->get_scope()); ROSE_ASSERT(classDefinition != NULL); SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); // std::cout << "subclass" << std::endl; // Iterate over all of the methods defined in this subclass. SgDeclarationStatementPtrList &decls = subclass->get_members(); for (SgDeclarationStatementPtrList::iterator declIter = decls.begin(); declIter != decls.end(); ++declIter) { SgDeclarationStatement *declStmt = *declIter; ROSE_ASSERT(declStmt != NULL); SgMemberFunctionDeclaration *method = isSgMemberFunctionDeclaration(declStmt); if ( method == NULL ) { continue; } // std::cout << "checking overrides" << std::endl; // Determine whether subclass of the class defining this // method overrides the method. #if 1 if ( matchingFunctions(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; // Do not consider a pure virtual method to be an // overriding method (since it can not be invoked). if ( !isPureVirtual(method) ) { numResolutionsForMethod++; } } #else if ( methodOverridesVirtualMethod(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; numResolutionsForMethod++; } #endif } } if ( numResolutionsForMethod <= 1 ) numMonomorphicCallSites++; numPossibleResolutions += numResolutionsForMethod; if ( ( numResolutionsForMethod ) > 1 ) { std::cout << "Method invocation has " << numResolutionsForMethod << " possible resolutions " << std::endl; std::cout << functionCallExp->unparseToCompleteString() << std::endl; } } } #endif #endif return 0; }
void CompassAnalyses::VariableNameEqualsDatabaseName::Traversal:: visit(SgNode* node) { if( isSgAssignInitializer(node) != NULL ) assignExp = node; if( isSgAssignOp(node) != NULL ) assignExp = node; SgFunctionCallExp* funcCall = isSgFunctionCallExp(node); // See if we have a dot expression or arrow expression which // accesses the desired member function in the class we are looking for. if ( funcCall != NULL ) { SgExpression* funcExp = funcCall->get_function(); if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) ) { SgBinaryOp* binOp = isSgBinaryOp(funcExp); SgExpression* rhsOp = binOp->get_rhs_operand(); // SgExpression* lhsOp = binOp->get_lhs_operand(); if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp) ) { // std::cout << "c1\n" ; SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); ROSE_ASSERT(funcSymbol->get_declaration() != NULL); // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C) // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL); if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL) { SgMemberFunctionDeclaration* funcDecl = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration()); ROSE_ASSERT( funcDecl != NULL ); SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope()); SgClassDeclaration* clDecl = isSgClassDeclaration(clDef->get_declaration()); // SgClassDeclaration* clDecl = funcDecl->get_associatedClassDeclaration(); ROSE_ASSERT( clDecl != NULL ); std::string className = clDecl->get_name().getString(); ROSE_ASSERT(funcDecl != NULL); std::string functionName = funcDecl->get_name().getString(); // If the class is the class we are looking for see if the member function // access is to the member function we are interested in. // std::cout << "className = " << className << std::endl; // std::cout << "functionName = " << functionName << std::endl; if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) ) { SgExprListExp* actualArgs = funcCall->get_args(); SgExpressionPtrList& actualExpArgs = actualArgs->get_expressions (); ROSE_ASSERT(actualExpArgs.size() == 1); Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal); ROSE_ASSERT( nodeLst.size() > 0); SgStringVal* actualArg = isSgStringVal(*nodeLst.begin()); ROSE_ASSERT(actualArg != NULL); std::string stringArg = actualArg->get_value(); std::cout << "arg:" << stringArg << std::endl; std::string varName; // SgInitializedName* initName = NULL; if ( SgAssignInitializer* assignInit = isSgAssignInitializer(assignExp) ) { SgInitializedName* initName = isSgInitializedName(assignInit->get_parent()); ROSE_ASSERT(initName != NULL); varName = initName->get_name().getString(); } else { if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) ) { SgExpression* lhsOp = assignOp->get_lhs_operand(); SgVarRefExp* varRef = isSgVarRefExp(lhsOp); ROSE_ASSERT(varRef!=NULL); SgVariableSymbol* varSymbol = varRef->get_symbol(); ROSE_ASSERT(varSymbol != NULL); SgInitializedName* initName = varSymbol->get_declaration(); varName = initName->get_name().getString(); } } if (varName != "") { // we are only interested in the part of the argument after the last ":" // Database scopes in ALE3D are separated by ":" size_t posCol = stringArg.find_last_of(':'); if (posCol != std::string::npos) stringArg = stringArg.substr(posCol+1); //Find violations to the rule if ( stringArg != varName) { output->addOutput(new CheckerOutput(assignExp)); std::cout << "violation" << varName << std::endl; } else { std::cout << "non=violation" << varName << std::endl; } } } } } } } } // End of the visit function.
void generateStencilCode(StencilEvaluationTraversal & traversal, bool generateLowlevelCode) { // Read the stencil and generate the inner most loop AST for the stencil. // Note that generateLowlevelCode controls the generation of low level C code using a // base pointer to raw memory and linearized indexing off of that pointer. The // alternative is to use the operator[] member function in the RectMDArray class. // Example of code that we want to generate: // for (j=0; j < source.size(0); j++) // { // int axis_x_size = source.size(0); // for (i=0; i < source.size(0); i++) // { // destination[j*axis_x_size+i] = source[j*axis_x_size+i]; // } // } // This function genertes the loop nest only: // SgForStatement* buildLoopNest(int stencilDimension, SgBasicBlock* & innerLoopBody) // This function generates the statement in the inner most loop body: // SgExprStatement* assembleStencilSubTreeArray(vector<SgExpression*> & stencilSubTreeArray) // This function generates the AST representing the stencil points: // SgExpression* buildStencilPoint (StencilOffsetFSM* stencilOffsetFSM, double stencilCoeficient, int stencilDimension, SgVariableSymbol* destinationVariableSymbol, SgVariableSymbol* sourceVariableSymbol) // The generated code should be in terms of the operator[]() functions on the // RectMDArray objects. Likely we have to support a wider range of generated code later. // const RectMDArray<TDest>& a_LOfPhi, // const RectMDArray<TSrc>& a_phi, // std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList; std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList = traversal.get_stencilOperatorFunctionCallList(); for (size_t i = 0; i < stencilOperatorFunctionCallList.size(); i++) { SgFunctionCallExp* functionCallExp = stencilOperatorFunctionCallList[i]; ROSE_ASSERT(functionCallExp != NULL); printf ("processing functionCallExp = %p \n",functionCallExp); SgStatement* associatedStatement = TransformationSupport::getStatement(functionCallExp); ROSE_ASSERT(associatedStatement != NULL); string filename = associatedStatement->get_file_info()->get_filename(); int lineNumber = associatedStatement->get_file_info()->get_line(); printf ("Generating code for stencil operator used at file = %s at line = %d \n",filename.c_str(),lineNumber); SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // There should be four elements to a stencil operator. ROSE_ASSERT(argumentList->get_expressions().size() == 4); // Stencil SgExpression* stencilExpression = argumentList->get_expressions()[0]; SgVarRefExp* stencilVarRefExp = isSgVarRefExp(stencilExpression); ROSE_ASSERT(stencilVarRefExp != NULL); // RectMDArray (destination) SgExpression* destinationArrayReferenceExpression = argumentList->get_expressions()[1]; SgVarRefExp* destinationArrayVarRefExp = isSgVarRefExp(destinationArrayReferenceExpression); ROSE_ASSERT(destinationArrayVarRefExp != NULL); // RectMDArray (source) SgExpression* sourceArrayReferenceExpression = argumentList->get_expressions()[2]; SgVarRefExp* sourceArrayVarRefExp = isSgVarRefExp(sourceArrayReferenceExpression); ROSE_ASSERT(sourceArrayVarRefExp != NULL); // Box SgExpression* boxReferenceExpression = argumentList->get_expressions()[3]; SgVarRefExp* boxVarRefExp = isSgVarRefExp(boxReferenceExpression); ROSE_ASSERT(boxVarRefExp != NULL); printf ("DONE: processing inputs to stencil operator \n"); ROSE_ASSERT(stencilVarRefExp->get_symbol() != NULL); SgInitializedName* stencilInitializedName = stencilVarRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(stencilInitializedName != NULL); string stencilName = stencilInitializedName->get_name(); printf ("stencilName = %s \n",stencilName.c_str()); std::map<std::string,StencilFSM*> & stencilMap = traversal.get_stencilMap(); ROSE_ASSERT(stencilMap.find(stencilName) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[stencilName]; ROSE_ASSERT(stencilFSM != NULL); // DQ (2/8/2015): Moved out of loop. int stencilDimension = stencilFSM->stencilDimension(); ROSE_ASSERT(stencilDimension > 0); // These are computed values. printf ("Stencil dimension = %d \n",stencilDimension); printf ("Stencil width = %d \n",stencilFSM->stencilWidth()); std::vector<std::pair<StencilOffsetFSM,double> > & stencilPointList = stencilFSM->stencilPointList; // This is the scope where the stencil operator is evaluated. SgScopeStatement* outerScope = associatedStatement->get_scope(); ROSE_ASSERT(outerScope != NULL); SgVariableSymbol* indexVariableSymbol_X = NULL; SgVariableSymbol* indexVariableSymbol_Y = NULL; SgVariableSymbol* indexVariableSymbol_Z = NULL; SgVariableSymbol* arraySizeVariableSymbol_X = NULL; SgVariableSymbol* arraySizeVariableSymbol_Y = NULL; SgVariableSymbol* destinationVariableSymbol = destinationArrayVarRefExp->get_symbol(); ROSE_ASSERT(destinationVariableSymbol != NULL); SgVariableSymbol* sourceVariableSymbol = sourceArrayVarRefExp->get_symbol(); ROSE_ASSERT(sourceVariableSymbol != NULL); SgVariableSymbol* boxVariableSymbol = boxVarRefExp->get_symbol(); ROSE_ASSERT(boxVariableSymbol != NULL); // This can be important in handling of comments and CPP directives. bool autoMovePreprocessingInfo = true; SgStatement* lastStatement = associatedStatement; if (generateLowlevelCode == true) { #if 1 SgVariableDeclaration* sourceDataPointerVariableDeclaration = buildDataPointer("sourceDataPointer",sourceVariableSymbol,outerScope); #else // Optionally build a pointer variable so that we can optionally support a C style indexing for the DTEC DSL blocks. SgExpression* sourcePointerExp = buildMemberFunctionCall(sourceVariableSymbol,"getPointer",NULL,false); ROSE_ASSERT(sourcePointerExp != NULL); SgAssignInitializer* assignInitializer = SageBuilder::buildAssignInitializer_nfi(sourcePointerExp); ROSE_ASSERT(assignInitializer != NULL); // Build the variable declaration for the pointer to the data. string sourcePointerName = "sourceDataPointer"; SgVariableDeclaration* sourceDataPointerVariableDeclaration = SageBuilder::buildVariableDeclaration_nfi(sourcePointerName,SageBuilder::buildPointerType(SageBuilder::buildDoubleType()),assignInitializer,outerScope); ROSE_ASSERT(sourceDataPointerVariableDeclaration != NULL); #endif // SageInterface::insertStatementAfter(associatedStatement,forStatementScope,autoMovePreprocessingInfo); SageInterface::insertStatementAfter(associatedStatement,sourceDataPointerVariableDeclaration,autoMovePreprocessingInfo); SgVariableDeclaration* destinationDataPointerVariableDeclaration = buildDataPointer("destinationDataPointer",destinationVariableSymbol,outerScope); SageInterface::insertStatementAfter(sourceDataPointerVariableDeclaration,destinationDataPointerVariableDeclaration,autoMovePreprocessingInfo); // Reset the variable symbols we will use in the buildStencilPoint() function. sourceVariableSymbol = SageInterface::getFirstVarSym(sourceDataPointerVariableDeclaration); destinationVariableSymbol = SageInterface::getFirstVarSym(destinationDataPointerVariableDeclaration); lastStatement = destinationDataPointerVariableDeclaration; } SgBasicBlock* innerLoopBody = NULL; // SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,sourceVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,boxVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); ROSE_ASSERT(innerLoopBody != NULL); ROSE_ASSERT(lastStatement != NULL); SageInterface::insertStatementAfter(lastStatement,loopNest,autoMovePreprocessingInfo); // Mark this as compiler generated so that it will not be unparsed. associatedStatement->get_file_info()->setCompilerGenerated(); // Form an array of AST subtrees to represent the different points in the stencil. // vector<SgFunctionCallExp*> stencilSubTreeArray; vector<SgExpression*> stencilSubTreeArray; for (size_t j = 0; j < stencilPointList.size(); j++) { #if 0 printf ("Forming stencil point subtree for offsetValues[0] = %3d [1] = %3d [2] = %3d \n",stencilPointList[j].first.offsetValues[0],stencilPointList[j].first.offsetValues[1],stencilPointList[j].first.offsetValues[2]); #endif StencilOffsetFSM* stencilOffsetFSM = &(stencilPointList[j].first); double stencilCoeficient = stencilPointList[j].second; // SgFunctionCallExp* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilFSM->stencilDimension()); SgExpression* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilDimension,sourceVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencilSubTree != NULL); stencilSubTreeArray.push_back(stencilSubTree); } // Construct the lhs value for the stencil inner loop statement. StencilOffsetFSM* stencilOffsetFSM_lhs = new StencilOffsetFSM(0,0,0); double stencilCoeficient_lhs = 1.00; SgExpression* stencil_lhs = buildStencilPoint(stencilOffsetFSM_lhs,stencilCoeficient_lhs,stencilDimension,destinationVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencil_lhs != NULL); // Assemble the stencilSubTreeArray into a single expression. SgExprStatement* stencilStatement = assembleStencilSubTreeArray(stencil_lhs,stencilSubTreeArray,stencilDimension,destinationVariableSymbol); SageInterface::appendStatement(stencilStatement,innerLoopBody); } }
//Generates SSA form numbers for the variables contained in *ex and attaches them as AstValueAttributes to the related SgNodes //Assumption: *ex 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::processSgExpression(SgExpression* ex, Label* condLabel, bool inTrueBranch) { SgIntVal* intVal = dynamic_cast<SgIntVal*>(ex); SgMinusOp* minusOp = dynamic_cast<SgMinusOp*>(ex); SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(ex); SgBinaryOp* binOp = dynamic_cast<SgBinaryOp*>(ex); SgFunctionCallExp* funcCall = dynamic_cast<SgFunctionCallExp*>(ex); if(intVal) //Int value { //Nothing needs to be done; Case is listed here to have a collection of all expected cases } else if(minusOp) { processSgExpression(minusOp->get_operand(), condLabel, inTrueBranch); } else if(varRef) //Reference to variable that is NOT on the left hand side of an assignment { //Assign number to variable string varName = varRef->get_symbol()->get_name().getString(); int varNumber = currentNumber(varName, condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Current number for variable " << varName << ": " << varNumber << endl; AstValueAttribute<int>* varNumberAtt = new AstValueAttribute<int>(varNumber); varRef->setAttribute("SSA_NUMBER", varNumberAtt); } else if(binOp) //Binary operation { SgExpression* lhs = binOp->get_lhs_operand(); SgExpression* rhs = binOp->get_rhs_operand(); //Process right hand side first processSgExpression(rhs, condLabel, inTrueBranch); //Process left hand side second SgAssignOp* assignOp = dynamic_cast<SgAssignOp*>(binOp); if(assignOp) //Assignment to a variable { //Assign new number to that variable SgVarRefExp* lhsVarRef = dynamic_cast<SgVarRefExp*>(lhs); assert(lhsVarRef != NULL); processAssignmentTo(lhsVarRef, condLabel, inTrueBranch); } else //Arithmetic operation or boolean operation (or something unexpected) { processSgExpression(lhs, condLabel, inTrueBranch); } } else if(funcCall) //Call to a function //RERS specific; Only two function call types are supported: //(1) scanf("%d",&...); //(2) __VERIFIER_error(RERSVerifierErrorNumber); The artificial bool variable RERSErrorOccured has to be updated { string funcName = funcCall->getAssociatedFunctionSymbol()->get_name().getString(); logger[Sawyer::Message::DEBUG] << "Call to function: " << funcName << endl; if(funcName == "scanf") //(1) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); SgExpressionPtrList::iterator i = funcArgsPtrs.begin(); while(i != funcArgsPtrs.end()) { SgAddressOfOp* addrOp = dynamic_cast<SgAddressOfOp*>(*i); if(addrOp) { SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(addrOp->get_operand()); if(varRef) { processAssignmentTo(varRef, condLabel, inTrueBranch); } else logger[Sawyer::Message::DEBUG] << "FOUND NO REFERENCE TO VARIABLE" << endl; } i++; } } else if(funcName == "__VERIFIER_error" && prepareReachabilityAnalysisZ3) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); assert(funcArgsPtrs.size() == 1); SgExpression* argument = *funcArgsPtrs.begin(); SgIntVal* intArgument = dynamic_cast<SgIntVal*>(argument); assert(intArgument != NULL); if(intArgument->get_value() == RERSVerifierErrorNumber) //(2) { int RERSErrorOccuredNumber = nextNumber("RERSErrorOccured", condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Next number for variable RERSErrorOccured: " << RERSErrorOccuredNumber << endl; AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(RERSErrorOccuredNumber); funcCall->setAttribute("SSA_NUMBER", numberAtt); } } else logger[Sawyer::Message::DEBUG] << "Ignoring function call" << endl; } else //Unexpected { logger[Sawyer::Message::ERROR] << "ERROR: SgExpression could not be handled: " << ex->class_name() << endl; assert(false); } }
// first visits the VarRef and then creates entry in operandDatabase which is // useful in expressionStatement transformation. Thus, we replace the VarRef // at the end of the traversal and insert loops during traversal ArrayAssignmentStatementQuerySynthesizedAttributeType ArrayAssignmentStatementTransformation::evaluateSynthesizedAttribute( SgNode* astNode, ArrayAssignmentStatementQueryInheritedAttributeType arrayAssignmentStatementQueryInheritedData, SubTreeSynthesizedAttributes synthesizedAttributeList) { // This function assembles the elements of the input list (a list of char*) to form the output (a single char*) #if DEBUG printf ("\n$$$$$ TOP of evaluateSynthesizedAttribute (astNode = %s) (synthesizedAttributeList.size() = %d) \n", astNode->sage_class_name(),synthesizedAttributeList.size()); //cout << " Ast node string: " << astNode->unparseToString() << endl; #endif // Build the return value for this function ArrayAssignmentStatementQuerySynthesizedAttributeType returnSynthesizedAttribute(astNode); // Iterator used within several error checking loops (not sure we should declare it here!) vector<ArrayAssignmentStatementQuerySynthesizedAttributeType>::iterator i; // Make a reference to the global operand database OperandDataBaseType & operandDataBase = accumulatorValue.operandDataBase; // Make sure the data base has been setup properly ROSE_ASSERT(operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess); ROSE_ASSERT(operandDataBase.dimension > -1); // Build up a return string string returnString = ""; string operatorString; // Need to handle all unary and binary operators and variables (but not much else) switch (astNode->variant()) { case FUNC_CALL: { // Error checking: Verify that we have a SgFunctionCallExp object SgFunctionCallExp* functionCallExpression = isSgFunctionCallExp(astNode); ROSE_ASSERT(functionCallExpression != NULL); string operatorName = TransformationSupport::getFunctionName(functionCallExpression); ROSE_ASSERT(operatorName.c_str() != NULL); string functionTypeName = TransformationSupport::getFunctionTypeName(functionCallExpression); if ((functionTypeName != "doubleArray") && (functionTypeName != "floatArray") && (functionTypeName != "intArray")) { // Use this query to handle only A++ function call expressions // printf ("Break out of overloaded operator processing since type = %s is not to be processed \n",functionTypeName.c_str()); break; } else { // printf ("Processing overloaded operator of type = %s \n",functionTypeName.c_str()); } ROSE_ASSERT((functionTypeName == "doubleArray") || (functionTypeName == "floatArray") || (functionTypeName == "intArray")); // printf ("CASE FUNC_CALL: Overloaded operator = %s \n",operatorName.c_str()); // Get the number of parameters to this function SgExprListExp* exprListExp = functionCallExpression->get_args(); ROSE_ASSERT(exprListExp != NULL); SgExpressionPtrList & expressionPtrList = exprListExp->get_expressions(); int numberOfParameters = expressionPtrList.size(); TransformationSupport::operatorCodeType operatorCodeVariant = TransformationSupport::classifyOverloadedOperator(operatorName.c_str(), numberOfParameters); // printf ("CASE FUNC_CALL: numberOfParameters = %d operatorCodeVariant = %d \n", // numberOfParameters,operatorCodeVariant); ROSE_ASSERT(operatorName.length() > 0); // Separating this case into additional cases makes up to some // extent for using a more specific higher level grammar. switch (operatorCodeVariant) { case TransformationSupport::ASSIGN_OPERATOR_CODE: { vector<ArrayOperandDataBase>::iterator lhs = operandDataBase.arrayOperandList.begin(); vector<ArrayOperandDataBase>::iterator rhs = lhs; rhs++; while (rhs != operandDataBase.arrayOperandList.end()) { // look at the operands on the rhs for a match with the one on the lhs if ((*lhs).arrayVariableName == (*rhs).arrayVariableName) { // A loop dependence has been identified // Mark the synthesized attribute to record // the loop dependence within this statement returnSynthesizedAttribute.setLoopDependence(TRUE); } rhs++; } break; } default: break; } break; } case EXPR_STMT: { printf("Found a EXPR STMT expression %s\n", astNode->unparseToString().c_str()); // The assembly associated with the SgExprStatement is what // triggers the generation of the transformation string SgExprStatement* expressionStatement = isSgExprStatement(astNode); ROSE_ASSERT(expressionStatement != NULL); ArrayAssignmentStatementQuerySynthesizedAttributeType innerLoopTransformation = synthesizedAttributeList[SgExprStatement_expression]; // Call another global support // Create appropriate macros, nested loops, etc expressionStatementTransformation(expressionStatement, arrayAssignmentStatementQueryInheritedData, innerLoopTransformation, operandDataBase); break; } // case TransformationSupport::PARENTHESIS_OPERATOR_CODE: { // ROSE_ASSERT (operatorName == "operator()"); // // printf ("Indexing of InternalIndex objects in not implemented yet! \n"); // // // Now get the operands out and search for the offsets in the index objects // // // We only want to pass on the transformationOptions as inherited attributes // // to the indexOffsetQuery // // list<int> & transformationOptionList = arrayAssignmentStatementQueryInheritedData.getTransformationOptions(); // // // string offsetString; // string indexOffsetString[6]; // = {NULL,NULL,NULL,NULL,NULL,NULL}; // // // retrieve the variable name from the data base (so that we can add the associated index object names) // // printf ("WARNING (WHICH OPERAND TO SELECT): operandDataBase.size() = %d \n",operandDataBase.size()); // // ROSE_ASSERT (operandDataBase.size() == 1); // // string arrayVariableName = returnSynthesizedAttribute.arrayOperandList[0].arrayVariableName; // int lastOperandInDataBase = operandDataBase.size() - 1; // ArrayOperandDataBase & arrayOperandDB = operandDataBase.arrayOperandList[lastOperandInDataBase]; // // string arrayVariableName = // // operandDataBase.arrayOperandList[operandDataBase.size()-1].arrayVariableName; // string arrayVariableName = arrayOperandDB.arrayVariableName; // // string arrayDataPointerNameSubstring = string("_") + arrayVariableName; // // // printf ("***** WARNING: Need to get identifier from the database using the ArrayOperandDataBase::generateIdentifierString() function \n"); // // if (expressionPtrList.size() == 0) { // // Case of A() (index object with no offset integer expression) Nothing to do here (I think???) // printf("Special case of Indexing with no offset! exiting ... \n"); // ROSE_ABORT(); // // returnString = ""; // } else { // // Get the value of the offsets (start the search from the functionCallExp) // SgExprListExp* exprListExp = functionCallExpression->get_args(); // ROSE_ASSERT (exprListExp != NULL); // // SgExpressionPtrList & expressionPtrList = exprListExp->get_expressions(); // SgExpressionPtrList::iterator i = expressionPtrList.begin(); // // // Case of indexing objects used within operator() // int counter = 0; // while (i != expressionPtrList.end()) { // // printf ("Looking for the offset on #%d of %d (total) \n",counter,expressionPtrList.size()); // // // Build up the name of the final index variable (or at least give // // it a unique number by dimension) // string counterString = StringUtility::numberToString(counter + 1); // // // Call another transformation mechanism to generate string for the index // // expression (since we don't have an unparser mechanism in ROSE yet) // indexOffsetString[counter] = IndexOffsetQuery::transformation(*i); // // ROSE_ASSERT (indexOffsetString[counter].c_str() != NULL); // // printf ("indexOffsetString [%d] = %s \n",counter,indexOffsetString[counter].c_str()); // // // Accumulate a list of all the InternalIndex, Index, and Range objects // printf(" Warning - Need to handle indexNameList from the older code \n"); // // i++; // counter++; // } // Added VAR_REF case (moved from the local function) case VAR_REF: { // A VAR_REF has to output a string (the variable name) #if DEBUG printf ("Found a variable reference expression \n"); #endif // Since we are at a leaf in the traversal of the AST this attribute list should a size of 0. ROSE_ASSERT(synthesizedAttributeList.size() == 0); SgVarRefExp* varRefExp = isSgVarRefExp(astNode); ROSE_ASSERT(varRefExp != NULL); SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT(initializedName != NULL); SgName variableName = initializedName->get_name(); string buffer; string indexOffsetString; // Now compute the offset to the index objects (form a special query for this???) SgType* type = variableSymbol->get_type(); ROSE_ASSERT(type != NULL); string typeName = TransformationSupport::getTypeName(type); ROSE_ASSERT(typeName.c_str() != NULL); // Recognize only these types at present if (typeName == "intArray" || typeName == "floatArray" || typeName == "doubleArray") { // Only define the variable name if we are using an object of array type // Copy the string from the SgName object to a string object string variableNameString = variableName.str(); #if DEBUG printf("Handle case of A++ array object VariableName: %s \n", variableNameString.c_str()); #endif if (arrayAssignmentStatementQueryInheritedData.arrayStatementDimensionDefined == TRUE) { cout << " Dim: " << arrayAssignmentStatementQueryInheritedData.arrayStatementDimension << endl; // The the globally computed array dimension from the arrayAssignmentStatementQueryInheritedData dimensionList.push_back(arrayAssignmentStatementQueryInheritedData.arrayStatementDimension); } else { dimensionList.push_back(6); // Default dimension for A++/P++ } nodeList.push_back(isSgExpression(varRefExp)); //processArrayRefExp(varRefExp, arrayAssignmentStatementQueryInheritedData); // Setup an intry in the synthesized attribute data base for this variable any // future results from analysis could be place there at this point as well // record the name in the synthesized attribute ROSE_ASSERT(operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess); ArrayOperandDataBase arrayOperandDB = operandDataBase.setVariableName(variableNameString); } break; } default: { break; } } // End of main switch statement #if DEBUG printf ("$$$$$ BOTTOM of arrayAssignmentStatementAssembly::evaluateSynthesizedAttribute (astNode = %s) \n",astNode->sage_class_name()); printf (" BOTTOM: returnString = \n%s \n",returnString.c_str()); #endif return returnSynthesizedAttribute; }
int main( int argc, char* argv[] ) { // Initialize and check compatibility. See rose::initialize ROSE_INITIALIZE; SgProject* project = frontend(argc,argv); AstTests::runAllTests(project); #if 0 // Output the graph so that we can see the whole AST graph, for debugging. generateAstGraph(project, 4000); #endif #if 1 printf ("Generate the dot output of the SAGE III AST \n"); generateDOT ( *project ); printf ("DONE: Generate the dot output of the SAGE III AST \n"); #endif // There are lots of way to write this, this is one simple approach; get all the function calls. std::vector<SgNode*> functionCalls = NodeQuery::querySubTree (project,V_SgFunctionCallExp); // Find the SgFunctionSymbol for snprintf so that we can reset references to "sprintf" to "snprintf" instead. // SgGlobal* globalScope = (*project)[0]->get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(project->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal* globalScope = sourceFile->get_globalScope(); SgFunctionSymbol* snprintf_functionSymbol = globalScope->lookup_function_symbol("snprintf"); ROSE_ASSERT(snprintf_functionSymbol != NULL); // Iterate over the function calls to find the calls to "sprintf" for (unsigned long i = 0; i < functionCalls.size(); i++) { SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(functionCalls[i]); ROSE_ASSERT(functionCallExp != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); if (functionSymbol != NULL) { SgName functionName = functionSymbol->get_name(); // printf ("Function being called: %s \n",functionName.str()); if (functionName == "sprintf") { // Now we have something to do! functionRefExp->set_symbol(snprintf_functionSymbol); // Now add the "n" argument SgExprListExp* functionArguments = functionCallExp->get_args(); SgExpressionPtrList & functionArgumentList = functionArguments->get_expressions(); // "sprintf" shuld have exactly 2 arguments (I guess the "..." don't count) printf ("functionArgumentList.size() = %zu \n",functionArgumentList.size()); // ROSE_ASSERT(functionArgumentList.size() == 2); SgExpressionPtrList::iterator i = functionArgumentList.begin(); // printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str()); SgVarRefExp* variableRefExp = isSgVarRefExp(*i); ROSE_ASSERT(variableRefExp != NULL); // printf ("variableRefExp->get_type() = %p = %s = %s \n",variableRefExp->get_type(),variableRefExp->get_type()->class_name().c_str(),SageInterface::get_name(variableRefExp->get_type()).c_str()); SgType* bufferType = variableRefExp->get_type(); SgExpression* bufferLengthExpression = NULL; switch(bufferType->variantT()) { case V_SgArrayType: { SgArrayType* arrayType = isSgArrayType(bufferType); bufferLengthExpression = arrayType->get_index(); break; } case V_SgPointerType: { // SgPointerType* pointerType = isSgPointerType(bufferType); SgInitializedName* variableDeclaration = variableRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(variableDeclaration != NULL); SgExpression* initializer = variableDeclaration->get_initializer(); if (initializer != NULL) { SgAssignInitializer* assignmentInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignmentInitializer != NULL); // This is the rhs of the initialization of the pointer (likely a malloc through a cast). // This assumes: buffer = (char*) malloc(bufferLengthExpression); SgExpression* initializationExpression = assignmentInitializer->get_operand(); ROSE_ASSERT(initializationExpression != NULL); SgCastExp* castExp = isSgCastExp(initializationExpression); ROSE_ASSERT(castExp != NULL); SgFunctionCallExp* functionCall = isSgFunctionCallExp(castExp->get_operand()); ROSE_ASSERT(functionCall != NULL); SgExprListExp* functionArguments = isSgExprListExp(functionCall->get_args()); bufferLengthExpression = functionArguments->get_expressions()[0]; ROSE_ASSERT(bufferLengthExpression != NULL); } else { printf ("Initializer not found, so no value for n in snprintf can be computed currently \n"); } break; } default: { printf ("Error: default reached in evaluation of buffer type = %p = %s \n",bufferType,bufferType->class_name().c_str()); ROSE_ASSERT(false); } } ROSE_ASSERT(bufferLengthExpression != NULL); // printf ("bufferLengthExpression = %p = %s = %s \n",bufferLengthExpression,bufferLengthExpression->class_name().c_str(),SageInterface::get_name(bufferLengthExpression).c_str()); // Jump over the first argument, the "n" is defined to be the 2nd argument (the rest are shifted one position). i++; // Build a deep copy of the expression used to define the static buffer (could be any complex expression). SgTreeCopy copy_help; SgExpression* bufferLengthExpression_copy = isSgExpression(bufferLengthExpression->copy(copy_help)); // Insert the "n" for the parameter list to work with "snprintf" instead of "sprintf" functionArgumentList.insert(i,bufferLengthExpression_copy); } } } } return backend(project); }