#include #include #include #include #include #include "../GraphCall/graph_calls.h" #include "../Utils/errors.h" #include "../Utils/utils.h" #include "sage++user.h" #include "definesValues.h" #include "set.h" #include "definitionSet.h" using std::map; using std::string; using std::vector; using std::wstring; #ifdef __SPF extern "C" void addToCollection(const int line, const char *file, void *pointer, int type); extern "C" void removeFromCollection(void *pointer); #endif // // Global table to store the use and def // // Not used anymore, replaced by attributes; // SgExpression *Used[MAXNODE]; // SgExpression *Defined[MAXNODE]; // // declaration for the data flow framework // extern Set *genSet[MAXNODE]; extern Set *killSet[MAXNODE]; extern Set *inSet[MAXNODE]; extern Set *outSet[MAXNODE]; extern void iterativeForwardFlowAnalysis(SgFile *file, SgStatement *func, Set *(*giveGenSet)(SgStatement *func, SgStatement *stmt), Set *(*giveKillSet)(SgStatement *func, SgStatement *stmt), int(*feq)(void *e1, void *e2), void *(*fcomb)(void *e1, void *e2), void(*fp)(void *e1)); extern void generalIterativeFlowAnalysis(SgFile *file, SgStatement *func, Set *(*transfertSet)(SgStatement *func, SgStatement *stmt, Set *setin), int(*feq)(void *e1, void *e2), void* (*fcomb)(void *e1, void *e2), void(*fp)(void *e1)); ///////////////////////////////////////////////////////////////////// // from the intrinsic.C file ///////////////////////////////////////////////////////////////////// extern int isSymbolIntrinsic(SgSymbol *symb); ///////////////////////////////////////////////////////////////////// // computes the definition for each file; ///////////////////////////////////////////////////////////////////// static inline bool isVarRef(SgExpression *ex) { const int var = ex->variant(); return (var == ARRAY_REF || var == VAR_REF || var == ARRAY_OP); } static void fillDef(SgExpression *ex, vector &useL, vector &defL, const map &funcs, vector &messagesForFile, const int currLine); static void fillUse(SgExpression *ex, vector &useL, vector &defL, const map &funcs, vector &messagesForFile, const int currLine) { if (ex) { if (isVarRef(ex)) { useL.push_back(ex); fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine); fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine); } else if (ex->variant() == FUNC_CALL) fillDef(ex, useL, defL, funcs, messagesForFile, currLine); else { fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine); fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine); } } } static void fillDef(SgExpression *ex, vector &useL, vector &defL, const map &funcs, vector &messagesForFile, const int currLine) { if (ex) { if (ex->variant() == FUNC_CALL) { bool isIntrinsic = isSymbolIntrinsic(ex->symbol()); SgFunctionCallExp *call = (SgFunctionCallExp*)ex; FuncInfo *currInfo = NULL; auto it = funcs.find(call->funName()->identifier()); if (funcs.end() != it) { currInfo = it->second; if (currInfo->funcParams.countOfPars != call->numberOfArgs()) { wstring bufE, bufR; __spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str()); __spf_printToLongBuf(bufR, R82, to_wstring(currInfo->funcName).c_str()); messagesForFile.push_back(Messages(ERROR, currLine, bufR, bufE, 1046)); throw -991; } } for (int z = 0; z < call->numberOfArgs(); ++z) { SgExpression *arg = call->arg(z); if (isVarRef(arg)) { if (currInfo) { if (currInfo->funcParams.isArgOut(z)) defL.push_back(arg); } else { if (!isIntrinsic) defL.push_back(arg); } useL.push_back(arg); } fillUse(arg->lhs(), useL, defL, funcs, messagesForFile, currLine); fillUse(arg->rhs(), useL, defL, funcs, messagesForFile, currLine); } } else { fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine); fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine); } } } SgExpression* makeList(const std::vector &vec) { if (vec.size() == 0) return NULL; SgExpression *list = new SgExpression(EXPR_LIST); SgExpression *r_list = list; for (int i = 0; i < vec.size(); ++i) { list->setLhs(vec[i]); if (i != vec.size() - 1) { list->setRhs(new SgExpression(EXPR_LIST)); list = list->rhs(); } } return r_list; } static void defUseVar(SgStatement *stmt, SgStatement *func, SgExpression **def, SgExpression **use, const map &allFuncs, vector &messagesForFile) { SgExpression *expr1, *expr2; SgExpression *temp, *pt, *pt1; SgArrayRefExp *aref; SgExprListExp *exprli; SgFunctionCallExp *fc; SgInputOutputStmt *iostmt; SgCallStmt *callStat; if (!stmt || !func) return; *def = NULL; *use = NULL; switch (stmt->variant()) { case ASSIGN_STAT: expr1 = stmt->expr(0); expr2 = stmt->expr(1); // need to be recursively applied later; if (expr1) *def = expr1->symbRefs(); else *def = NULL; if (expr2) *use = expr2->symbRefs(); else *use = NULL; for (temp = *def; temp; temp = temp->rhs()) { if (aref = isSgArrayRefExp(temp->lhs())) { pt = aref->subscripts(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (*use) { if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } else *use = pt1; } } } for (temp = *use; temp; temp = temp->rhs()) { if (aref = isSgArrayRefExp(temp->lhs())) { pt = aref->subscripts(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } } if (fc = isSgFunctionCallExp(temp->lhs())) { FuncInfo *currInfo = NULL; auto it = allFuncs.find(fc->funName()->identifier()); if (allFuncs.end() != it) { currInfo = it->second; if (currInfo->funcParams.countOfPars != fc->numberOfArgs()) { wstring bufE, bufR; __spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str()); __spf_printToLongBuf(bufR, R83, to_wstring(currInfo->funcName).c_str()); messagesForFile.push_back(Messages(ERROR, stmt->lineNumber(), bufR, bufE, 1046)); throw -991; } } pt = fc->args(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } //new algo if (currInfo) { vector defL; vector useL; fillDef(fc, useL, defL, allFuncs, messagesForFile, stmt->lineNumber()); if (defL.size()) { SgExpression *list = makeList(defL); if (exprli = isSgExprListExp(*def)) exprli->linkToEnd(*list); else *def = list; } } //old algo else { // if not an intrinsic, needs to be added to the def list; if (!isSymbolIntrinsic(fc->funName())) { pt1 = pt->symbRefs(); if (pt1 && (exprli = isSgExprListExp(*def))) { exprli->linkToEnd(*pt1); } else *def = pt1; } } } } } break; case FOR_NODE: { SgExprListExp *el; SgVarRefExp *vr; if (stmt->symbol()) { vr = new SgVarRefExp(*(stmt->symbol())); *def = new SgExprListExp(*vr); *use = new SgExprListExp(*vr); } else { *use = NULL; *def = NULL; } // Borne inf and sup are also sunject to use; expr1 = stmt->expr(0); expr2 = stmt->expr(1); // need to be recursively applied later; if (expr1) { pt1 = expr1->symbRefs(); if (*use) { if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } else *use = pt1; } if (expr2) { pt1 = expr2->symbRefs(); if (*use) { if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } else *use = pt1; } for (temp = *use; temp; temp = temp->rhs()) { if (aref = isSgArrayRefExp(temp->lhs())) { pt = aref->subscripts(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } } if (fc = isSgFunctionCallExp(temp->lhs())) { pt = fc->args(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } // if not an intrinsic, needs to be added to the def list; if (!isSymbolIntrinsic(fc->funName())) { pt1 = pt->symbRefs(); if (pt1 && (exprli = isSgExprListExp(*def))) { exprli->linkToEnd(*pt1); } else *def = pt1; } } } } } break; case LOGIF_NODE: case CONT_STAT: case CONTROL_END: // here we should check if loop... case IF_NODE: case WHILE_NODE: case DO_WHILE_NODE: expr2 = stmt->expr(0); // need to be recursively applied later; if (expr2) *use = expr2->symbRefs(); else *use = NULL; *def = NULL; for (temp = *use; temp; temp = temp->rhs()) { if (aref = isSgArrayRefExp(temp->lhs())) { pt = aref->subscripts(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } } } if (fc = isSgFunctionCallExp(temp->lhs())) { pt = fc->args(); if (pt) { pt1 = pt->symbRefs(); // we add it to the end of use; if (pt1 && (exprli = isSgExprListExp(*use))) { exprli->linkToEnd(*pt1); } // if not an intrinsic, needs to be added to the def list; if (!isSymbolIntrinsic(fc->funName())) { pt1 = pt->symbRefs(); if (pt1 && (exprli = isSgExprListExp(*def))) { exprli->linkToEnd(*pt1); } else *def = pt1; } } } } break; case READ_STAT: iostmt = isSgInputOutputStmt(stmt); if (iostmt) { if (iostmt->itemList()) *def = iostmt->itemList()->symbRefs(); else *def = NULL; *use = NULL; } else Message("internal error : IO statements not found\n", 0); break; case WRITE_STAT: case PRINT_STAT: iostmt = isSgInputOutputStmt(stmt); if (iostmt) { if (iostmt->itemList()) *use = iostmt->itemList()->symbRefs(); else *use = NULL; *def = NULL; } else Message("internal error : IO statements not found\n", 0); break; case PROC_STAT: callStat = (SgCallStmt*)stmt; pt = callStat->expr(0); if (pt) { /**use = pt->symbRefs(); // if not an intrinsic, needs to be added to the def list; if (!isSymbolIntrinsic(callStat->name())) *def = pt->symbRefs(); printf("old use:\n"); recExpressionPrint(*use); printf("old def:\n"); recExpressionPrint(*def);*/ vector defL; vector useL; FuncInfo *currInfo = NULL; auto it = allFuncs.find(callStat->name()->identifier()); if (allFuncs.end() != it) { currInfo = it->second; if (currInfo->funcParams.countOfPars != callStat->numberOfArgs()) { wstring bufE, bufR; __spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str()); __spf_printToLongBuf(bufR, R84, to_wstring(currInfo->funcName).c_str()); messagesForFile.push_back(Messages(ERROR, stmt->lineNumber(), bufR, bufE, 1046)); throw -991; } } for (int z = 0; z < callStat->numberOfArgs(); ++z) { SgExpression *arg = callStat->arg(z); if (isVarRef(arg)) { if (currInfo) { if (currInfo->funcParams.isArgOut(z)) defL.push_back(arg); } else defL.push_back(arg); useL.push_back(arg); } fillUse(arg->lhs(), useL, defL, allFuncs, messagesForFile, callStat->lineNumber()); fillUse(arg->rhs(), useL, defL, allFuncs, messagesForFile, callStat->lineNumber()); } *use = makeList(useL); *def = makeList(defL); /*printf("new use:\n"); recExpressionPrint(*use); printf("new def:\n"); recExpressionPrint(*def); printf("");*/ } else { *def = NULL; *use = NULL; } break; case GOTO_NODE: case STOP_STAT: case RETURN_STAT: case RETURN_NODE: case ELSEIF_NODE: case ARITHIF_NODE: case WHERE_NODE: case WHERE_BLOCK_STMT: case SWITCH_NODE: case CASE_NODE: case BREAK_NODE: case EXIT_STMT: case ASSGOTO_NODE: case COMGOTO_NODE: default: *def = NULL; *use = NULL; break; } } void initDefUseTable(SgStatement *func, const map &allFuncs, vector &messagesForFile) { SgStatement *last, *first, *lastfunc, *temp; SgExpression *def, *use, *pt; int i; int nbatt, typeat, j; if (!func) return; lastfunc = func->lastNodeOfStmt(); for (temp = func; temp; temp = temp->lexNext()) { if (isSgExecutableStatement(temp)) { nbatt = temp->numberOfAttributes(); for (j = 0; j < nbatt; j++) { typeat = temp->attributeType(j); if ((typeat == USEDLIST_ATTRIBUTE) || (typeat == DEFINEDLIST_ATTRIBUTE)) { temp->deleteAttribute(j); j--; } } } if (temp == lastfunc) break; } for (temp = func; temp; temp = temp->lexNext()) { if (isSgExecutableStatement(temp)) { defUseVar(temp, func, &def, &use, allFuncs, messagesForFile); temp->addAttribute(USEDLIST_ATTRIBUTE, (void*)use, 0); temp->addAttribute(DEFINEDLIST_ATTRIBUTE, (void*)def, 0); } if (temp == lastfunc) break; } } // // Example of functions for flow analysis // int symbRefEqual(void *e1, void *e2) { SgExpression *ex1, *ex2; SgSymbol *s1, *s2; PT_ELSET el1, el2; if (!e1 && !e2) return 1; if (!e1 || !e2) return 0; el1 = (PT_ELSET)e1; el2 = (PT_ELSET)e2; ex1 = el1->expr; ex2 = el2->expr; if ((s1 = ex1->symbol()) && (s2 = ex2->symbol())) { if (s1 == s2) { if (el1->stmt == el2->stmt) return 1; else return 0; } else return 0; } else return 0; } void myPrint(void *e1) { SgExpression *ex1; PT_ELSET el1; if (!e1) return; el1 = (PT_ELSET)e1; ex1 = el1->expr; if (el1->stmt) printf("(id = %d, line = %d, ", el1->stmt->id(), el1->stmt->lineNumber()); else printf("(id = -, line = -, "); if (ex1->symbol()) printf("%s", ex1->symbol()->identifier()); else ex1->unparsestdout(); printf(")"); printf(","); } // // Example of function to compute gen and kill sets for Reaching Definition. // NOARRAYREF indicate if we want array ref in Set *makeGenSet(SgStatement *func, SgStatement *stmt) { SgExpression *def, *use, *pt; PT_ELSET el; Set *defset, *pts; if (!func || !stmt) return NULL; def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE); // Defined[stmt->id()]; defset = new Set(symbRefEqual, NULL, myPrint); #ifdef __SPF addToCollection(__LINE__, __FILE__, defset, 1); #endif if (def) { for (pt = def; pt; pt = pt->rhs()) { if (!isSgTypeExp(pt->lhs())) { if (!NOARRAYREF || !isSgArrayRefExp(pt->lhs())) { el = new struct elset; #ifdef __SPF addToCollection(__LINE__, __FILE__, el, 1); #endif el->stmt = stmt; el->expr = pt->lhs(); defset->addElement((void *)el); } } } } pts = defset; // printf("Printing defset:\n"); // defset->printSet(); defset = defset->compact(); if (pts) { #ifdef __SPF removeFromCollection(pts); #endif delete pts; } // defset->printSet(); return defset; } Set *makeKillSet(SgStatement *func, SgStatement *stmt) { SgExpression *def, *use, *pt, *defstmt, *expr1, *pt1; PT_ELSET el; Set *killset, *pts; SgStatement *last, *first, *lastfunc, *temp; int trouve; if (!func || !stmt) return NULL; killset = new Set(symbRefEqual, NULL, myPrint); #ifdef __SPF addToCollection(__LINE__, __FILE__, killset, 1); #endif last = func->lastNodeOfStmt(); defstmt = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE); //Defined[stmt->id()]; if (defstmt) { for (pt1 = defstmt; pt1; pt1 = pt1->rhs()) { expr1 = pt1->lhs(); if (!isSgArrayRefExp(expr1) && !isSgTypeExp(expr1)) { // cannot kill an array ref; for (temp = func; temp; temp = temp->lexNext()) { if (temp != stmt) { if (def = (SgExpression *)temp->attributeValue(0, DEFINEDLIST_ATTRIBUTE)) //Defined[temp->id()]) { for (pt = def; pt; pt = pt->rhs()) { if (pt->lhs()) { if (pt->lhs()->symbol() == expr1->symbol()) { el = new struct elset; #ifdef __SPF addToCollection(__LINE__, __FILE__, el, 1); #endif el->stmt = temp; el->expr = pt->lhs(); killset->addElement((void *)el); } } } } } if (temp == last) break; } } } } pts = killset; // printf("Printing killset:\n"); // killset->printSet(); killset = killset->compact(); // killset->printSet(); if (pts) { #ifdef __SPF removeFromCollection(pts); #endif delete pts; } return killset; }