#include "../Utils/leak_detector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #else #include #endif #include "SgUtils.h" #include "errors.h" #include "../Sapfor.h" #include "../DirectiveProcessing/directive_parser.h" #include "../Distribution/Distribution.h" #include "../GraphCall/graph_calls.h" #include "../GraphCall/graph_calls_func.h" #include "../CreateInterTree/CreateInterTree.h" #include "../Predictor/PredictScheme.h" #include "../VisualizerCalls/get_information.h" #include "../VisualizerCalls/SendMessage.h" #include "../VerificationCode/verifications.h" #include "../LoopAnalyzer/loop_analyzer.h" using std::map; using std::queue; using std::multimap; using std::pair; using std::tuple; using std::set; using std::vector; using std::string; using std::make_pair; using std::make_tuple; using std::wstring; using std::stack; static bool ifIntervalExists(const vector> &intervals, const pair &toFind, pair& inInterval) { bool retVal = false; for (auto &elem : intervals) { if (toFind.first <= elem.first && toFind.second >= elem.second) { inInterval = elem; retVal = true; break; } } return retVal; } static bool ifDir(const string &line) { if (line.size() >= 10 && (line[0] == '!' || line[0] == 'c')) { string dir(line.begin() + 1, line.begin() + 1 + 4); if (dir == "$spf" || dir == "dvm$") return true; } return false; } static string replaceTabsToSpaces(const string &in) { string ret = ""; for (auto &elem : in) { if (elem == '\t') ret += " "; else ret += elem; } return ret; } static map> > > findIncludes(FILE *currFile) { map> > > includeFiles; bool notClosed = false; // TODO: extend buff size in dynamic char buf[8192]; int lineBefore = 0; while (!feof(currFile)) { char *read = fgets(buf, 8192, currFile); if (read) { const string orig(replaceTabsToSpaces(read)); string line(read); convertToLower(line); line = replaceTabsToSpaces(line); size_t posF = line.find("include"); if (posF != string::npos) { //check if 'inclide' - operator for (size_t k = 0; k < posF; ++k) { if (line[k] != ' ') { posF = -1; break; } } if (posF == -1) { ++lineBefore; continue; } posF += sizeof("include") - 1; int tok = 0; size_t st = string::npos, en = string::npos; for (size_t k = posF; k < line.size(); ++k) { bool isQuote = line[k] == '\'' || line[k] == '\"'; if (isQuote && tok == 1) break; else if (isQuote) tok++; else if (tok == 1 && st == string::npos) st = k; else en = k; } if (st == string::npos || st >= line.size() || en == string::npos || en >= line.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const string inclName(orig.begin() + st, orig.begin() + en + 1); auto toInsert = includeFiles.find(inclName); if (toInsert == includeFiles.end()) { toInsert = includeFiles.insert(toInsert, make_pair(inclName, make_pair(orig, vector>()))); toInsert->second.second.push_back(make_pair(lineBefore, -1)); notClosed = true; } else { toInsert->second.second.push_back(make_pair(lineBefore, -1)); notClosed = true; } //printf("insert %s -> %s\n", inclName.c_str(), line.c_str()); } else if ((line[0] != 'c' && line[0] != '!' && line != "" && line[0] != '\n') || ifDir(line)) { if (notClosed) { for (auto &elem : includeFiles) for (auto &pair : elem.second.second) if (pair.second == -1) pair.second = lineBefore + 1; notClosed = false; } } } ++lineBefore; } return includeFiles; } static vector findCommentsInIncludes(map> > >& includeFiles) { vector foundComments; for (auto& elem : includeFiles) { FILE* inclFile = fopen(elem.first.c_str(), "r"); if (inclFile == NULL) { char buf[256]; sprintf(buf, "ERROR: Can't open inlcude file %s for read with err %d\n", elem.first.c_str(), errno); addToGlobalBufferAndPrint(buf); continue; } char buf[8192]; int lineBefore = 0; string newComment = ""; while (!feof(inclFile)) { char* read = fgets(buf, 8192, inclFile); if (read) { string orig(replaceTabsToSpaces(read)); if (orig.size() && (orig[0] == 'C' || orig[0] == 'c')) { orig[0] = '!'; newComment += orig; continue; } int k = 0; while (k < orig.size()) { if (orig[k] == ' ') ++k; else break; } // remove first spaces if (k > 0) orig.erase(orig.begin(), orig.begin() + k); if (orig.size()) { if (orig[0] == '!') newComment += read; else if (newComment != "") { foundComments.push_back(newComment); newComment = ""; } } else if (newComment != "") { foundComments.push_back(newComment); newComment = ""; } } } if (newComment != "") { foundComments.push_back(newComment); newComment = ""; } fclose(inclFile); } return foundComments; } static int reverseVar(SgStatement* st) { st->setVariant(-1 * st->variant()); return st->id(); } static map>> insertedIncludes; static set genVersionDone; static set hideUnnecessary(SgFile* file, const string& fileN, const set& moduleDeclsInFiles, bool dontReplaceIncludes) { set changedVars; for (SgStatement* st = file->firstStatement(); st; st = st->lexNext()) { if (st->variant() == GLOBAL) continue; if (dontReplaceIncludes == false) { if (st->fileName() != fileN || st->getUnparseIgnore()) if (st->variant() > 0) changedVars.insert(reverseVar(st)); } else { if (st->getUnparseIgnore()) { if (st->variant() > 0) changedVars.insert(reverseVar(st)); } else if (st->fileName() != fileN) { if (st->variant() == MODULE_STMT && moduleDeclsInFiles.find(st->fileName()) != moduleDeclsInFiles.end()) { for (auto mSt = st; mSt != st->lastNodeOfStmt(); mSt = mSt->lexNext()) changedVars.insert(reverseVar(mSt)); st = st->lastNodeOfStmt(); changedVars.insert(reverseVar(st)); } } } } return changedVars; } //TODO: read includes and find last lines, all included files string removeIncludeStatsAndUnparse(SgFile *file, const char *fileName, const char *fout, set &allIncludeFiles, bool outFree, const map>& moduleUsesByFile, const map& moduleDelcs, const map>& exctactedModuleStats, bool toString, bool renameIncludes, bool dontReplaceIncludes) { removeSpecialCommentsFromProject(file); if (genVersionDone.find(file) == genVersionDone.end()) { auto firstStat = file->firstStatement(); auto com = printVersionAsFortranComm(); if (com != "") firstStat->addComment(com.c_str()); genVersionDone.insert(file); } fflush(NULL); const set modulesExclude = getExcludedModules(); set moduleIncudeUses; auto itM = moduleUsesByFile.find(fileName); if (itM != moduleUsesByFile.end()) { for (auto& elem : itM->second) { auto it2 = moduleDelcs.find(elem); if (it2 == moduleDelcs.end()) { if (modulesExclude.find(elem) != modulesExclude.end()) continue; __spf_print(1, "can not find module '%s'\n", elem.c_str()); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } string lowerInclude = it2->second; convertToLower(lowerInclude); moduleIncudeUses.insert(lowerInclude); } } int funcNum = file->numberOfFunctions(); FILE *currFile = fopen(fileName, "r"); if (currFile == NULL) { char buf[256]; sprintf(buf, "ERROR: Can't open file %s for read with err %d\n", fileName, errno); addToGlobalBufferAndPrint(buf); char buff[1024]; if (getcwd(buff, 1024) == NULL) ;// else __spf_print(1, "curr path %s\n", buff); throw(-1); } // name -> unparse comment and position map> > > includeFiles = findIncludes(currFile); fclose(currFile); const vector commentsFromIncl = findCommentsInIncludes(includeFiles); //add spaces if needed if (!outFree) { for (auto &elem : includeFiles) { int countSpaces = 0; for (int z = 0; z < elem.second.first.size() && elem.second.first[z] == ' '; ++z, ++countSpaces) { } if (countSpaces < 6) { while (countSpaces != 6) { elem.second.first.insert(elem.second.first.begin(), ' '); countSpaces++; } } } } const string fileN = fileName; //insert comment int lineBefore = -1; map> insertedIncludeFiles; map>> placesForInsert; set foundForIncludes; map stIdByLine; for (SgStatement* st = file->firstStatement(); st; st = st->lexNext()) { if (st->variant() > 0 && st->lineNumber() > 0 && st->fileName() == string(file->filename())) { stIdByLine[st->lineNumber()] = st->id(); vector attr = getAttributes(st, set{SPF_ANALYSIS_DIR, SPF_NOINLINE_OP}); for (auto& elem : attr) if (stIdByLine.find(elem->lineNumber()) == stIdByLine.end()) stIdByLine[elem->lineNumber()] = st->id(); } } auto fileInProject = getAllFilesInProject(); for (SgStatement *st = file->firstStatement(); st; st = st->lexNext()) { if (st->lineNumber() <= 0 || st->variant() < 0) continue; string currFileName = st->fileName(); // included for module use if (currFileName != fileN && fileInProject.find(currFileName) != fileInProject.end()) { st = st->lastNodeOfStmt(); continue; } if (currFileName != fileN) { allIncludeFiles.insert(currFileName); auto it = includeFiles.find(currFileName); if (it != includeFiles.end()) { foundForIncludes.insert(currFileName); pair lines = make_pair(lineBefore, -1); SgStatement *locSt = st->lexNext(); set nearIncludes; while (locSt && (locSt->fileName() != fileN || locSt->lineNumber() <= 0)) { const string locName = locSt->fileName(); if (locName != fileN) { allIncludeFiles.insert(locName); if (locName != currFileName) { auto itNear = includeFiles.find(locName); if (itNear != includeFiles.end()) { nearIncludes.insert(locName); foundForIncludes.insert(locName); } } } locSt = locSt->lexNext(); } if (locSt) { lines.second = locSt->lineNumber(); st = locSt; bool change = true; while (change) { change = false; SgStatement *prev = locSt->lexPrev(); if (prev && (prev->variant() == DVM_PARALLEL_ON_DIR || prev->variant() == SPF_ANALYSIS_DIR || prev->variant() == SPF_TRANSFORM_DIR || prev->variant() == DVM_INTERVAL_DIR || prev->variant() == ACC_REGION_DIR || prev->variant() == DVM_REALIGN_DIR || prev->variant() == DVM_REDISTRIBUTE_DIR)) { locSt = prev; change = true; } } placesForInsert[locSt->id()].push_back(lines); } } } else lineBefore = st->lineNumber(); } //if not found, it indicates that file contains of other include files for (auto& incl : includeFiles) { if (foundForIncludes.find(incl.first) == foundForIncludes.end()) { for (auto& interval : incl.second.second) { bool added = false; for (int z = interval.second; z > interval.first; z--) { auto it = stIdByLine.find(z); if (it != stIdByLine.end()) { placesForInsert[it->second].push_back(interval); added = true; break; } } if (added == false) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } } } for (SgStatement *st = file->firstStatement(); st; st = st->lexNext()) { if (st->variant() < 0) continue; auto itGlobal = insertedIncludes.find(st); if (itGlobal == insertedIncludes.end()) itGlobal = insertedIncludes.insert(itGlobal, make_pair(st, map>())); map>& toInsertIncludeComment = itGlobal->second; bool needUpdated = false; for (auto &it : includeFiles) { auto foundV = placesForInsert.find(st->id()); if (foundV != placesForInsert.end()) { SgStatement* parent = getFuncStat(st, { BLOCK_DATA, MODULE_STMT }); if(!parent) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& interval : foundV->second) { pair inInterval; if (ifIntervalExists(it.second.second, interval, inInterval) && insertedIncludeFiles[it.first].find(parent) == insertedIncludeFiles[it.first].end()) { allIncludeFiles.insert(it.first); insertedIncludeFiles[it.first].insert(parent); string lowerInclude = it.first; convertToLower(lowerInclude); if (moduleIncudeUses.find(lowerInclude) == moduleIncudeUses.end()) { if (dontReplaceIncludes == false) { auto itI = toInsertIncludeComment.find(inInterval.first); if (itI == toInsertIncludeComment.end() || (itI != toInsertIncludeComment.end() && itI->second.find(it.second.first) == itI->second.end())) { toInsertIncludeComment[inInterval.first].insert(it.second.first); needUpdated = true; __spf_print(1, " --> restore include '%s' before statement on line %d\n", it.first.c_str(), st->lineNumber()); } } } } } } } if (needUpdated) { string inlcude = ""; for (auto& inclByPos : toInsertIncludeComment) for (auto& incl : inclByPos.second) inlcude += (renameIncludes ? renameInclude(incl) : incl); if (st->comments()) st->setComments((inlcude + st->comments()).c_str()); else st->addComment(inlcude.c_str()); } } for (auto &inserted : insertedIncludeFiles) { auto it = includeFiles.find(inserted.first); if (it == includeFiles.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //TODO: dont work after subroutine copying /*if (inserted.second.size() != it->second.second.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__);*/ } set moduleDeclsInFiles; for (auto& elem : moduleDelcs) moduleDeclsInFiles.insert(elem.second); //restore hidden modules vector toExtract; for (auto& mod : exctactedModuleStats) { auto cp = mod.first->controlParent(); for (auto& toInsert : mod.second) { mod.first->insertStmtBefore(*toInsert, *cp); toExtract.push_back(toInsert); } } //remove unnecessary //XXX: use Sage hack!! set changedVars = hideUnnecessary(file, fileN, moduleDeclsInFiles, dontReplaceIncludes); set checkPositions; for (auto& elem : includeFiles) for (auto& interval : elem.second.second) checkPositions.insert(interval.second); // remove comments that were substituted from includes for (SgStatement* st = file->firstStatement(); st; st = st->lexNext()) { const char* comments = st->comments(); if (st->fileName() == fileN && st->variant() > 0 && comments && !dontReplaceIncludes) { if (checkPositions.find(st->lineNumber()) != checkPositions.end()) { //printf("%s\n", comments); string str(comments); bool wasDeleted = false; for (auto& com : commentsFromIncl) { auto it = str.find(com); while (it != string::npos) { wasDeleted = true; str.erase(it, com.size()); it = str.find(com); } if (str.size() == 0) break; } if (wasDeleted) { if (str.size() || str.back() != '\n') str += '\n'; st->setComments(str.c_str()); } } } } //check for empty string comm = ""; if (file->firstStatement()->comments()) { comm = file->firstStatement()->comments(); file->firstStatement()->delComments(); } const string tmp = file->firstStatement()->unparse(); bool isEmpty = (tmp.size() == 0); if (comm.size()) file->firstStatement()->addComment(comm.c_str()); string strUnparse = ""; if (toString) { if (!isEmpty) strUnparse = string(file->firstStatement()->unparse()); } else { if (!isEmpty) { #ifdef _WIN32 FILE* fOut; errno_t err = fopen_s(&fOut, fout, "w"); #else int err = 0; FILE* fOut = fopen(fout, "w"); #endif if (fOut == NULL) { if (fout) __spf_print(1, "can not open file to write with name '%s' with error %d\n", fout, err); else __spf_print(1, "can not open file to write with name 'NULL'\n"); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } file->unparse(fOut); fclose(fOut); } } //restore back //XXX: use Sage hack!! for (SgStatement *st = file->firstStatement(); st; st = st->lexNext()) if (changedVars.find(st->id()) != changedVars.end()) st->setVariant(-1 * st->variant()); for (auto& elem : toExtract) elem->extractStmt(); return strUnparse; } static map>> allCreatedSymbols; SgSymbol* findSymbolOrCreate(SgFile *file, const string toFind, SgType *type, SgStatement *scope) { auto createdSymbols = allCreatedSymbols.find(file); if (createdSymbols == allCreatedSymbols.end()) createdSymbols = allCreatedSymbols.insert(createdSymbols, make_pair(file, map>())); SgSymbol *symb = file->firstSymbol(); while (symb) { if (symb->identifier() == toFind) { bool scopeC = false; bool typeC = false; if (scope) scopeC = (symb->scope() == scope); else scopeC = true; if (type) typeC = (symb->type() && symb->type()->equivalentToType(type)); else typeC = true; if (scopeC && typeC) return symb; } symb = symb->next(); } auto result = createdSymbols->second.find(toFind); if (result == createdSymbols->second.end()) result = createdSymbols->second.insert(result, make_pair(toFind, vector())); SgSymbol *newS = NULL; for (auto &symbs : result->second) { if ((symbs->scope() == scope && scope) || (!symbs->scope() && !scope)) { if (symbs->type() && type) { if (symbs->type()->equivalentToType(type)) { newS = symbs; break; } } else if (!symbs->type() && !type) { newS = symbs; break; } } } if (newS == NULL) { newS = new SgSymbol(VARIABLE_NAME, toFind.c_str(), type, scope); result->second.push_back(newS); } return newS; } static string getValue(SgExpression *exp) { if (exp == NULL || exp->variant() == STMT_STR) return ""; string ret = ""; if (exp->variant() == CONST_REF) { if (exp->symbol()->identifier()) { ret = "(" + string(exp->symbol()->identifier()); auto sc = isSgConstantSymb(exp->symbol()); if (sc && sc->constantValue()) ret += string("=") + sc->constantValue()->unparse(); ret += ")"; } } else if (exp->symbol()) { if (exp->symbol()->identifier()) ret = "(" + string(exp->symbol()->identifier()) + ")"; } else if (exp->variant() == INT_VAL) ret = "(" + std::to_string(exp->valueInteger()) + ")"; else if (exp->variant() == DOUBLE_VAL) ret = string("(") + (((SgValueExp*)exp)->doubleValue()) + ")"; else if (exp->variant() == FLOAT_VAL) ret = string("(") + (((SgValueExp*)exp)->floatValue()) + ")"; else if (exp->variant() == ADD_OP) ret = "(+)"; else if (exp->variant() == SUBT_OP) ret = "(-)"; else if (exp->variant() == MULT_OP) ret = "(*)"; else if (exp->variant() == DIV_OP) ret = "(/)"; else if (exp->variant() == MOD_OP) ret = "(mod)"; else if (exp->variant() == EXP_OP) ret = "(**)"; else if (exp->variant() == KEYWORD_VAL) ret = "(" + string(((SgKeywordValExp*)exp)->value()) + ")"; return ret; } static void recExpressionPrint(SgExpression *exp, const int lvl, const char *LR, const int currNum, int &allNum) { if (exp) { SgExpression *lhs = exp->lhs(); SgExpression *rhs = exp->rhs(); int lNum, rNum; string vCurr = getValue(exp); string vL = getValue(lhs); string vR = getValue(rhs); if (lhs && rhs) { lNum = allNum + 1; rNum = allNum + 2; allNum += 2; printf("\"%d_%d_%s_%s_%s\" -> \"%d_%d_L_%s_%s\";\n", currNum, lvl, LR, tag[exp->variant()], vCurr.c_str(), lNum, lvl + 1, tag[lhs->variant()], vL.c_str()); printf("\"%d_%d_%s_%s_%s\" -> \"%d_%d_R_%s_%s\";\n", currNum, lvl, LR, tag[exp->variant()], vCurr.c_str(), rNum, lvl + 1, tag[rhs->variant()], vR.c_str()); } else if (lhs) { lNum = allNum + 1; allNum++; printf("\"%d_%d_%s_%s_%s\" -> \"%d_%d_L_%s_%s\";\n", currNum, lvl, LR, tag[exp->variant()], vCurr.c_str(), lNum, lvl + 1, tag[lhs->variant()], vL.c_str()); } else if (rhs) { rNum = allNum + 1; allNum++; printf("\"%d_%d_%s_%s_%s\" -> \"%d_%d_R_%s_%s\";\n", currNum, lvl, LR, tag[exp->variant()], vCurr.c_str(), rNum, lvl + 1, tag[rhs->variant()], vR.c_str()); } if (lhs) recExpressionPrint(lhs, lvl + 1, "L", lNum, allNum); if (rhs) recExpressionPrint(rhs, lvl + 1, "R", rNum, allNum); } } void recExpressionPrint(SgExpression *exp) { printf("digraph G{\n"); int allNum = 0; recExpressionPrint(exp, 0, "L", allNum, allNum); if (allNum == 0 && exp) printf("\"%d_%d_%s_%s_%s\";\n", allNum, 0, "L", tag[exp->variant()], getValue(exp).c_str()); printf("}\n"); fflush(NULL); } void initTags() { for (int i = 0; i < MAXTAGS; i++) tag[i] = NULL; #include "tag.h" } void tryToFindPrivateInAttributes(SgStatement *st, set &privates, bool onlyReduction, bool onlyUsers) { set privatesVars; auto foundAttrs = getAttributes(st, set{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR }); if (onlyUsers) foundAttrs = filterUserSpf(foundAttrs); for (auto &data : foundAttrs) { if (data) { Statement *sData = new Statement(data); if (!onlyReduction) fillPrivatesFromComment(sData, privatesVars); // try to find reductions and set its symbols as private in // current loop analysis for correct scalar detection in // tryToFindDependencies() function map> reductions; map>> reductionsLoc; fillReductionsFromComment(sData, reductions); fillReductionsFromComment(sData, reductionsLoc); for (auto &redList : reductions) privatesVars.insert(redList.second.begin(), redList.second.end()); for (auto &redLocList : reductionsLoc) { for (auto &groupList : redLocList.second) { privatesVars.insert(std::get<0>(groupList)); privatesVars.insert(std::get<1>(groupList)); } } } } for (auto& elem : privatesVars) privates.insert(elem->GetOriginal()->identifier()); } void fillNonDistrArraysAsPrivate(SgStatement *st, const map, pair> &declaredArrays, const map>> &declaratedArraysSt, set &privatesVars) { // fill as private all non distributed arrays auto it = declaratedArraysSt.find(st); if (it != declaratedArraysSt.end()) { for (auto itSet = it->second.begin(); itSet != it->second.end(); ++itSet) { auto itD = declaredArrays.find(*itSet); if (itD != declaredArrays.end()) if (itD->second.first->IsNotDistribute()) privatesVars.insert(itD->second.first->GetShortName()); } } } extern map, pair> declaredArrays; extern map>> declaratedArraysSt; DIST::Array* getArrayFromDeclarated(SgStatement *st, const string &arrayName) { DIST::Array *found = NULL; auto it = declaratedArraysSt.find(st); if (it != declaratedArraysSt.end()) { for (auto itSet = it->second.begin(); itSet != it->second.end() && !found; ++itSet) { auto itD = declaredArrays.find(*itSet); if (itD != declaredArrays.end()) if (itD->second.first->GetShortName() == arrayName) found = itD->second.first; } } return found; } static bool findSymbol(SgExpression *declLst, const string &toFind) { if (declLst == NULL) return false; stack exs; exs.push(declLst); while (!exs.empty()) { SgExpression* ex = exs.top(); exs.pop(); if (ex->variant() == ARRAY_REF || ex->variant() == VAR_REF || ex->variant() == CONST_REF) { if (ex->symbol()->identifier() == toFind) return true; } else { if (ex->lhs()) exs.push(ex->lhs()); if (ex->rhs()) exs.push(ex->rhs()); } } return false; } extern map> SPF_messages; SgStatement* declaratedInStmt(SgSymbol *toFind, vector *allDecls, bool printInternal, SgStatement* scope) { //need to call this function for MODULE symbols! toFind = OriginalSymbol(toFind); vector inDecl; if (toFind->variant() == FUNCTION_NAME && scope == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement *start = scope ? scope : toFind->scope(); if (start) { SgStatement *end = start->lastNodeOfStmt(); const set possibleVars = { VAR_DECL, VAR_DECL_90, ALLOCATABLE_STMT, DIM_STAT, EXTERN_STAT, COMM_STAT, HPF_TEMPLATE_STAT, DVM_VAR_DECL, STRUCT_DECL }; while (start != end) { //error ? if (start == NULL) break; if (start->variant() == INTERFACE_STMT) start = start->lastNodeOfStmt(); //printf("%d on line %d\n", start->variant(), start->lineNumber()); if (possibleVars.find(start->variant()) != possibleVars.end()) { for (int i = 0; i < 3; ++i) { SgExpression *declLst = start->expr(i); if (findSymbol(declLst, toFind->identifier())) inDecl.push_back(start); } } if (!isDVM_stat(start) && !isSPF_stat(start) && isSgExecutableStatement(start)) break; start = start->lexNext(); } } /*if (inDecl.size() == 0) { SgStatement *lowLevelDecl = toFind->declaredInStmt(); if (lowLevelDecl) inDecl.push_back(lowLevelDecl); }*/ if (inDecl.size() == 0) { if (printInternal) { __spf_print(1, "can not find declaration for symbol '%s'\n", toFind->identifier()); auto itM = SPF_messages.find(start->fileName()); if (itM == SPF_messages.end()) itM = SPF_messages.insert(itM, make_pair(start->fileName(), vector())); wstring bufE, bufR; __spf_printToLongBuf(bufE, L"Can not find declaration for symbol '%s' in current scope", to_wstring(toFind->identifier()).c_str()); __spf_printToLongBuf(bufR, R49, to_wstring(toFind->identifier()).c_str()); itM->second.push_back(Messages(ERROR, toFind->scope()->lineNumber(), bufR, bufE, 1017)); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } return NULL; } if (allDecls) *allDecls = inDecl; //return statement by priority: VAR_DECL, VAR_DECL_90, ALLOCATABLE_STMT, DIM_STAT, other if (inDecl.size() > 1) { for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == VAR_DECL || inDecl[i]->variant() == VAR_DECL_90) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == ALLOCATABLE_STMT) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == DIM_STAT) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == COMM_STAT) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == HPF_TEMPLATE_STAT) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) if (inDecl[i]->variant() == DVM_VAR_DECL) return inDecl[i]; for (int i = 0; i < inDecl.size(); ++i) return inDecl[i]; printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return NULL; } else return inDecl[0]; } bool isDVM_stat(SgStatement *st) { if (st == NULL) return false; bool ret = false; const int var = st->variant(); //for details see dvm_tag.h if ((var >= DVM_INTERVAL_DIR && var <= DVM_ENDINTERVAL_DIR) || (var >= DVM_DEBUG_DIR && var <= DVM_TRACEOFF_DIR) || (var >= DVM_PARALLEL_ON_DIR && var <= DVM_SHADOW_DIR) || (var >= DVM_NEW_VALUE_DIR && var <= DVM_POINTER_DIR) || (var >= DVM_TASK_REGION_DIR && var < FORALL_STAT) || (var > FORALL_STAT && var <= DVM_TEMPLATE_DELETE_DIR) || (var >= ACC_REGION_DIR && var <= ACC_ASYNC_OP) || (var == DVM_DISTRIBUTE_DIR) || (var >= HPF_TEMPLATE_STAT && var <= DVM_REDISTRIBUTE_DIR) || (var >= BLOCK_OP && var <= STAGE_OP) || (var >= INDIRECT_OP && var <= SHADOW_NAMES_OP) || (var >= ACC_REGION_DIR && var <= ACC_ASYNC_OP)) ret = true; return ret; } bool isSPF_stat(SgStatement *st) { if (st == NULL) return false; bool ret = false; const int var = st->variant(); //for details see dvm_tag.h if (var >= SPF_ANALYSIS_DIR && var <= SPF_PROCESS_PRIVATE_OP) ret = true; return ret; } static map::const_iterator getStringExpr(SgExpression *ex, map &collection) { auto it = collection.find(ex); if (it == collection.end()) it = collection.insert(it, make_pair(ex, ex->unparse())); return it; } bool isEqExpressions(SgExpression *left, SgExpression *right, map &collection) { if (left == right) return true; else if (left == NULL || right == NULL) return false; else return getStringExpr(left, collection)->second == getStringExpr(right, collection)->second; } static string getCommonName(SgExpression *common) { if (common->symbol()) return string(common->symbol()->identifier()); else return string("spf_unnamed"); } void getCommonBlocksRef(map> &commonBlocks, SgStatement *start, SgStatement *end, const string *nameToSkip) { while (start != end) { if (start->variant() == CONTAINS_STMT) break; if (start->variant() == COMM_STAT) { // fill all common blocks for (SgExpression *exp = start->expr(0); exp; exp = exp->rhs()) { const string commonName = getCommonName(exp); if (nameToSkip && *nameToSkip == commonName) continue; auto it = commonBlocks.find(commonName); if (it == commonBlocks.end()) it = commonBlocks.insert(it, make_pair(commonName, vector())); it->second.push_back(exp); } } start = start->lexNext(); } } int checkCommonInMainUnit(SgProject& project, map>& SPF_messages, const set& arrays, bool forDistrbuted) { int internalExit = 0; SgStatement* mainUnit = findMainUnit(&project, SPF_messages); checkNull(mainUnit, convertFileName(__FILE__).c_str(), __LINE__); map> commonBlocks; getCommonBlocksRef(commonBlocks, mainUnit, mainUnit->lastNodeOfStmt()); // check array declaration for (auto& array : arrays) { if (array->IsLoopArray() || array->IsTemplate()) continue; if (array->GetLocation().first == DIST::l_COMMON) { auto nameOfCommon = array->GetLocation().second; if (commonBlocks.find(nameOfCommon) == commonBlocks.end()) { auto declPlaces = array->GetDeclInfo(); for (auto& place : declPlaces) { vector& currMessages = getObjectForFileFromMap(place.first.c_str(), SPF_messages); if (forDistrbuted) { __spf_print(1, " ERROR: distributed array '%s' in common block '%s' must have declaration in main unit\n", array->GetShortName().c_str(), nameOfCommon.c_str()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"distributed array '%s' in common block '%s' must have declaration in main unit", to_wstring(array->GetShortName()).c_str(), to_wstring(nameOfCommon).c_str()); __spf_printToLongBuf(messageR, R75, to_wstring(array->GetShortName()).c_str(), to_wstring(nameOfCommon).c_str()); currMessages.push_back(Messages(ERROR, place.second, messageR, messageE, 1042)); } else { __spf_print(1, " ERROR: array '%s' in common block '%s' must have declaration in main unit for DECLARE insertion\n", array->GetShortName().c_str(), nameOfCommon.c_str()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array '%s' in common block '%s' must have declaration in main unit for DECLARE insertion", to_wstring(array->GetShortName()).c_str(), to_wstring(nameOfCommon).c_str()); __spf_printToLongBuf(messageR, R205, to_wstring(array->GetShortName()).c_str(), to_wstring(nameOfCommon).c_str()); currMessages.push_back(Messages(ERROR, place.second, messageR, messageE, 1062)); } } internalExit = 1; } } } return internalExit; } static SgExpression* isInCommon(const vector &commonBlocks, const char *arrayName, int &commonPos) { commonPos = 0; for (auto &common : commonBlocks) { for (SgExpression *currCommon = common->lhs(); currCommon; currCommon = currCommon->rhs()) { if (!strcmp(currCommon->lhs()->symbol()->identifier(), arrayName)) return common; commonPos++; } } return NULL; } static map, tuple> tableOfUniqNames; tuple getUniqName(const map> &commonBlocks, SgStatement *decl, SgSymbol *symb) { bool inCommon = false; bool needtoCheck = true; int commonPos = 0; SgExpression *foundCommon = NULL; SgStatement *declCP = decl->controlParent(); // find symbol in parameter list of functions if (declCP->variant() == PROC_HEDR || declCP->variant() == FUNC_HEDR) { if (declCP->variant() == PROC_HEDR) { const int num = ((SgProcHedrStmt*)declCP)->numberOfParameters(); for (int i = 0; i < num && needtoCheck; ++i) if (!strcmp(((SgProcHedrStmt*)declCP)->parameter(i)->identifier(), symb->identifier())) needtoCheck = false; } else { const int num = ((SgFuncHedrStmt*)declCP)->numberOfParameters(); for (int i = 0; i < num && needtoCheck; ++i) if (!strcmp(((SgFuncHedrStmt*)declCP)->parameter(i)->identifier(), symb->identifier())) needtoCheck = false; } auto declCpCp = declCP->controlParent(); if (declCpCp && declCpCp->variant() == INTERFACE_STMT && needtoCheck) needtoCheck = false; } else if (declCP->variant() == INTERFACE_STMT) needtoCheck = false; if (needtoCheck) { for (auto &common : commonBlocks) { foundCommon = isInCommon(common.second, symb->identifier(), commonPos); if (foundCommon) { inCommon = true; break; } } } tuple retVal; if (inCommon) retVal = make_tuple(commonPos, string("common_") + getCommonName(foundCommon), string(symb->identifier())); else retVal = make_tuple(decl->lineNumber(), string(decl->fileName()), string(symb->identifier())); auto key = make_tuple(symb->identifier(), decl->fileName(), decl->lineNumber()); auto it = tableOfUniqNames.find(key); if (it == tableOfUniqNames.end()) tableOfUniqNames.insert(it, make_pair(key, retVal)); else { if (it->first != key) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } return retVal; } tuple getFromUniqTable(SgSymbol *symb) { auto place = declaratedInStmt(symb); auto localIt = tableOfUniqNames.find(std::make_tuple(symb->identifier(), place->fileName(), place->lineNumber())); if (localIt == tableOfUniqNames.end()) { auto place = declaratedInStmt(symb); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } return localIt->second; } SgStatement* findMainUnit(SgProject *proj, map> &SPF_messages) { SgStatement *mainUnit = NULL; vector mainUnits; for (int i = proj->numberOfFiles() - 1; i >= 0; --i) { SgFile *file = &(proj->file(i)); const string file_name = file->filename(); for (int k = 0; k < file->numberOfFunctions(); ++k) { SgStatement *func = file->functions(k); if (func->variant() == PROG_HEDR && file_name == func->fileName()) { mainUnit = func; mainUnits.push_back(func); } } } if (mainUnits.size() != 1) { for (auto& elem : mainUnits) { vector& currMessages = getObjectForFileFromMap(elem->fileName(), SPF_messages); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"more than one main unit was found"); __spf_printToLongBuf(messageR, R146); currMessages.push_back(Messages(ERROR, elem->lineNumber(), messageR, messageE, 1050)); } if (mainUnits.size() == 0) { for (int i = proj->numberOfFiles() - 1; i >= 0; --i) { SgFile* file = &(proj->file(i)); const char* file_name = file->filename(); vector &currMessages = getObjectForFileFromMap(file_name, SPF_messages); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"main unit not found"); __spf_printToLongBuf(messageR, R147); currMessages.push_back(Messages(ERROR, file->firstStatement()->lexNext()->lineNumber(), messageR, messageE, 1050)); } } printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } if (!mainUnit->switchToFile()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return mainUnit; } template const vector getAttributes(IN_TYPE st, const set dataType) { vector outData; for (int i = 0; i < st->numberOfAttributes(); ++i) { SgAttribute *attr = st->getAttribute(i); const int type = st->attributeType(i); if (dataType.find(type) != dataType.end()) if (attr->getAttributeData()) outData.push_back((OUT_TYPE)(attr->getAttributeData())); } return outData; } template void deleteAttributes(IN_TYPE st, const set dataType) { bool changed = true; while (changed) { changed = false; int idxDel = -1; for (int i = 0; i < st->numberOfAttributes(); ++i) { SgAttribute* attr = st->getAttribute(i); const int type = st->attributeType(i); if (dataType.find(type) != dataType.end()) { if (attr->getAttributeData()) { idxDel = i; break; } } } if (idxDel != -1) { st->deleteAttribute(idxDel); changed = true; } } } template const vector getAttributes(SgSymbol *st, const set dataType); template const vector getAttributes(SgStatement* st, const set dataType); template const vector getAttributes(SgExpression* st, const set dataType); template const vector getAttributes(SgSymbol *st, const set dataType); template const vector getAttributes(SgSymbol* st, const set dataType); template const vector getAttributes(SgStatement *st, const set dataType); template const vector getAttributes(SgExpression *st, const set dataType); template const vector getAttributes(SgExpression *st, const set dataType); template const vector getAttributes(SgExpression *st, const set dataType); template const vector getAttributes(SgExpression *st, const set dataType); template const vector getAttributes(SgStatement *st, const set dataType); template void deleteAttributes(SgStatement* st, const set dataType); template void deleteAttributes(SgExpression* st, const set dataType); static int isParameterOneOfThese(const string& name, const vector& names) { int parameterOfFunctionItself = -1; for (int i = 0; i < names.size(); ++i) if (name == names[i]) { parameterOfFunctionItself = i; break; } return parameterOfFunctionItself; } #define DEF_T 0 #define USE_T 1 #define DEF_USE_T 2 static void processPartOfAssign(int type, SgExpression *exp, vector ¤tLists, SgFile *file, SgStatement *inStat, vector ¶meterNames, pair underCall, int funcPos); static void addSymbolsToDefUse(const int type, SgExpression *ex, vector ¤tList, pair underCall, int funcPos, SgFile *file, SgStatement *inStat, vector& parameterNames) { if (ex) { bool next = true; if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF) { if (ex->symbol()) { string name = string(ex->symbol()->identifier()); currentList.push_back(DefUseList(type, inStat, ex, file, underCall, make_pair(ex->symbol(), name), funcPos, isParameterOneOfThese(name, parameterNames))); } } else if (ex->variant() == FUNC_CALL) { underCall = make_pair(ex->symbol(), string(ex->symbol()->identifier())); funcPos = 0; bool isIntrinsic = isIntrinsicFunctionName(ex->symbol()->identifier()); for (SgExpression *list = ex->lhs(); list; list = list->rhs(), funcPos++) { if (!isIntrinsic) processPartOfAssign(DEF_USE_T, list->lhs(), currentList, file, inStat, parameterNames, underCall, funcPos); else addSymbolsToDefUse(type, list->lhs(), currentList, underCall, funcPos, file, inStat, parameterNames); } next = false; } if (next) { addSymbolsToDefUse(type, ex->lhs(), currentList, underCall, funcPos, file, inStat, parameterNames); addSymbolsToDefUse(type, ex->rhs(), currentList, underCall, funcPos, file, inStat, parameterNames); } } } static void processPartOfAssign(int type, SgExpression *exp, vector ¤tList, SgFile *file, SgStatement *inStat, vector ¶meterNames, pair underCall, int funcPos) { if (exp->symbol() && exp->variant() == VAR_REF) // simple assign { SgSymbol *tmp = exp->symbol(); string name = string(tmp->identifier()); if (type == DEF_USE_T) { currentList.push_back(DefUseList(DEF_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); currentList.push_back(DefUseList(USE_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); } else currentList.push_back(DefUseList(DEF_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); } //TODO else // array ref and etc. { if (exp->variant() == ARRAY_OP) { SgSymbol *tmp = exp->lhs()->symbol(); string name = string(tmp->identifier()); if (type == DEF_USE_T) { currentList.push_back(DefUseList(DEF_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); currentList.push_back(DefUseList(USE_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); } else currentList.push_back(DefUseList(type, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); addSymbolsToDefUse(1, exp->lhs()->lhs(), currentList, underCall, funcPos, file, inStat, parameterNames); addSymbolsToDefUse(1, exp->lhs()->rhs(), currentList, underCall, funcPos, file, inStat, parameterNames); } else if (exp->variant() == ARRAY_REF) { SgSymbol *tmp = exp->symbol(); string name = string(tmp->identifier()); if (type == DEF_USE_T) { currentList.push_back(DefUseList(DEF_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); currentList.push_back(DefUseList(USE_T, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); } else currentList.push_back(DefUseList(type, inStat, exp, file, underCall, make_pair(tmp, name), funcPos, isParameterOneOfThese(name, parameterNames))); addSymbolsToDefUse(1, exp->lhs(), currentList, underCall, funcPos, file, inStat, parameterNames); addSymbolsToDefUse(1, exp->rhs(), currentList, underCall, funcPos, file, inStat, parameterNames); } else { addSymbolsToDefUse(1, exp->lhs(), currentList, underCall, funcPos, file, inStat, parameterNames); addSymbolsToDefUse(1, exp->rhs(), currentList, underCall, funcPos, file, inStat, parameterNames); } } } static void inline addToLists(map> ¤tLists, const vector &tmpList) { for (auto &list : currentLists) for (auto &elem : tmpList) list.second.push_back(elem); } void constructDefUseStep1(SgFile *file, map> &defUseByFunctions, map> &allFuncInfo, vector &messages) { map> curFileFuncInfo; vector tmpL; map> tmpIR; functionAnalyzer(file, curFileFuncInfo, tmpL, messages, tmpIR); //functions not found if (curFileFuncInfo.size() == 0) return; auto whereToCopy = allFuncInfo.insert(make_pair(file->filename(), vector())); for(auto& it : curFileFuncInfo.begin()->second) whereToCopy.first->second.push_back(it); map funcToFuncInfo = map(); for (int i = 0; i < curFileFuncInfo.begin()->second.size(); ++i) funcToFuncInfo.insert(make_pair(curFileFuncInfo.begin()->second[i]->funcName, curFileFuncInfo.begin()->second[i])); for (int f = 0; f < file->numberOfFunctions(); ++f) { //function header and entry points map> currentLists; vector tmpList; vector parameterNames = vector(); SgStatement *start = file->functions(f); SgStatement *end = start->lastNodeOfStmt(); int pos; auto founded = funcToFuncInfo.find(((SgProgHedrStmt*)start)->nameWithContains()); start->addAttribute(PROC_CALL, (void*)founded->second, sizeof(FuncInfo)); SgProgHedrStmt *header = isSgProgHedrStmt(start); if (header && start->variant() != PROG_HEDR) for (int i = 0; i < header->numberOfParameters(); ++i) parameterNames.push_back(header->parameter(i)->identifier()); currentLists[string(start->symbol()->identifier())] = vector(); for (SgStatement *st = start->lexNext(); st != end; st = st->lexNext()) { if (isSgExecutableStatement(st)) { if (isDVM_stat(st)) { if (st->variant() != ACC_GET_ACTUAL_DIR && st->variant() != ACC_ACTUAL_DIR) continue; } tmpList.clear(); switch (st->variant()) { case ASSIGN_STAT: processPartOfAssign(DEF_T, st->expr(0), tmpList, file, st, parameterNames, make_pair((SgSymbol*)NULL, string("")), -1); addSymbolsToDefUse(USE_T, st->expr(1), tmpList, make_pair((SgSymbol*)NULL, string("")), -1, file, st, parameterNames); addToLists(currentLists, tmpList); break; case FOR_NODE: if (st->symbol()) for (auto &list : currentLists) { string name = string(st->symbol()->identifier()); auto vr = new SgVarRefExp(*(st->symbol())); list.second.push_back(DefUseList(1, st, vr, file, make_pair((SgSymbol*)NULL, string("")), make_pair(st->symbol(), name), -1, isParameterOneOfThese(name, parameterNames))); list.second.push_back(DefUseList(0, st, vr, file, make_pair((SgSymbol*)NULL, string("")), make_pair(st->symbol(), name), -1, isParameterOneOfThese(name, parameterNames))); } for (int i = 0; i < 3; ++i) addSymbolsToDefUse(USE_T, st->expr(i), tmpList, make_pair((SgSymbol*)NULL, string("")), -1, file, st, parameterNames); addToLists(currentLists, tmpList); break; case READ_STAT: { SgInputOutputStmt *io = isSgInputOutputStmt(st); auto list = io->itemList(); int pos = 0; while (list) { if (list->lhs()) processPartOfAssign(DEF_T, list->lhs(), tmpList, file, st, parameterNames, make_pair(io->symbol(), string("READ")), pos); pos++; list = list->rhs(); } } addToLists(currentLists, tmpList); break; case PROC_STAT: pos = 0; for (SgExpression *ex = st->expr(0); ex; ex = ex->rhs(), pos++) processPartOfAssign(DEF_USE_T, ex->lhs(), tmpList, file, st, parameterNames, make_pair(st->symbol(), string(st->symbol()->identifier())), pos); addToLists(currentLists, tmpList); break; case ENTRY_STAT: currentLists[string(st->symbol()->identifier())] = vector(); break; case LOGIF_NODE: case CONT_STAT: case IF_NODE: case WHILE_NODE: case DO_WHILE_NODE: 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: case WRITE_STAT: case PRINT_STAT: default: for (int i = 0; i < 3; ++i) addSymbolsToDefUse(USE_T, st->expr(i), tmpList, make_pair((SgSymbol*)NULL, string("")), -1, file, st, parameterNames); addToLists(currentLists, tmpList); break; } } } for (auto &list : currentLists) { auto it = defUseByFunctions.find(list.first); if (it == defUseByFunctions.end()) it = defUseByFunctions.insert(it, make_pair(list.first, vector())); } for (auto &list : currentLists) { auto it = defUseByFunctions.find(list.first); for (auto &elem : list.second) it->second.push_back(elem); } } } #undef DEF_T #undef USE_T #undef DEF_USE_T extern map> defUseByFunctions; set getAllDefVars(const string &funcName) { set retVal; for (auto &elem : defUseByFunctions[funcName]) if (elem.isDef()) retVal.insert(elem.getVar()); return retVal; } set getAllUseVars(const string &funcName) { set retVal; for (auto &elem : defUseByFunctions[funcName]) if (elem.isUse()) retVal.insert(elem.getVar()); return retVal; } const vector& getAllDefUseVarsList(const string &funcName) { return defUseByFunctions[funcName]; } const vector getAllDefUseVarsList(const string &funcName, const string varName) { vector retVal; for (auto &elem : defUseByFunctions[funcName]) if (elem.getVar() == varName) retVal.push_back(elem); return retVal; } map> createDefUseMapByPlace() { map> retVal; for (auto &byFunc : defUseByFunctions) for (auto &elem : byFunc.second) retVal[elem.getPlace()].push_back(elem); return retVal; } int printDefUseSets(const char *fileName, const map> &defUseLists) { FILE *file = fopen(fileName, "w"); if (file == NULL) { __spf_print(1, "can not open file %s\n", fileName); return -1; } for (auto &elem : defUseLists) { fprintf(file, "*** Function %s\n", elem.first.c_str()); for (auto &inList : elem.second) inList.print(file, true); fprintf(file, "\n"); } fclose(file); return 0; } static bool isDefUseVar(const int paramPosition, const string &funcName, map> &defUseByFunctions, bool defined) { auto founded = defUseByFunctions.find(funcName); if(founded == defUseByFunctions.end()) return true; //No information. Argument can be defined or used. vector& curDefUse = founded->second; bool isDefUse = false; for (int i = 0; i < curDefUse.size(); ++i) { if (paramPosition == curDefUse[i].getParameterPositionInFunction()) { if (defined && curDefUse[i].isDef()) { isDefUse = true; break; } else if(!defined && curDefUse[i].isUse()) { isDefUse = true; break; } else { const string calledFuncName = curDefUse[i].getParamOfFunction(); if (!calledFuncName.empty()) { isDefUse = isDefUseVar(curDefUse[i].getParameterPosition(), calledFuncName, defUseByFunctions, defined); if (isDefUse) break; } } } } return isDefUse; } static SgExpression* makeList(const vector &list) { if (list.size() == 0) return NULL; SgExpression *out = new SgExpression(EXPR_LIST); SgExpression *ret = out; for (int i = 0; i < list.size(); ++i) { out->setLhs(list[i]); if (i != list.size() - 1) { out->setRhs(new SgExpression(EXPR_LIST)); out = out->rhs(); } else out->setRhs(NULL); } return ret; } static map> buildLists(const vector &list) { map, vector>> out; for (auto &elem : list) { if (elem.isDef()) out[elem.getPlace()].first.push_back(elem.getExpr()); if (elem.isUse()) out[elem.getPlace()].second.push_back(elem.getExpr()); } map> ret; for (auto &elem : out) { ret[elem.first].first = makeList(elem.second.first); ret[elem.first].second = makeList(elem.second.second); } return ret; } void constructDefUseStep2(SgFile *file, map> &defUseByFunctions) { for (int f = 0; f < file->numberOfFunctions(); ++f) { SgProgHedrStmt *header = isSgProgHedrStmt(file->functions(f)); if (header == NULL || header->variant() == PROG_HEDR) continue; for (int i = 0; i < header->numberOfParameters(); ++i) { int currAttr = header->parameter(i)->attributes(); if ((currAttr & OUT_BIT) == 0 && (currAttr & INOUT_BIT) == 0 && (currAttr & IN_BIT) == 0) { bool isDef = isDefUseVar(i, header->symbol()->identifier(), defUseByFunctions, true); bool isUse = isDefUseVar(i, header->symbol()->identifier(), defUseByFunctions, false); if(isDef && isUse) header->parameter(i)->setAttribute(INOUT_BIT); else if (isDef) header->parameter(i)->setAttribute(OUT_BIT); else header->parameter(i)->setAttribute(IN_BIT); } //TODO: test and replace from defUseVar() in defUse.cpp /*auto funcList = defUseByFunctions[header->symbol()->identifier()]; auto toAdd = buildLists(funcList); for (auto &elem : toAdd) { elem.first->addAttribute(DEFINEDLIST_ATTRIBUTE, (void*)elem.second.first, 0); elem.first->addAttribute(USEDLIST_ATTRIBUTE, (void*)elem.second.second, 0); }*/ } } } int printCommonBlocks(const char *fileName, const map &commonBlocks) { FILE *file = fopen(fileName, "w"); if (file == NULL) { __spf_print(1, "can not open file %s\n", fileName); return -1; } for (auto &commonBlock : commonBlocks) { fprintf(file, "*** COMMON BLOCK '%s'\n", commonBlock.first.c_str()); commonBlock.second->print(file); fprintf(file, "\n"); } fclose(file); return 0; } // CommonBlock:: Variable* CommonBlock::hasVariable(const string &name, const varType type, const int position) { for (auto &variable : variables) if (variable->getName() == name && variable->getType() == type && variable->getPosition() == position) return variable; return NULL; } Variable* CommonBlock::hasVariable(SgSymbol *symbol, const varType type, const int position) { return hasVariable(string(symbol->identifier()), type, position); } const vector CommonBlock::getVariables(SgFile *file, SgStatement *function) const { return getVariables(string(file->filename()), string(function->symbol()->identifier())); } const vector CommonBlock::getVariables(const string &file, const string &function) const { vector retVariables; for (auto &variable : variables) if (variable->hasUse(file, function)) retVariables.push_back(variable); return retVariables; } const vector CommonBlock::getVariables(int position) const { vector retVariables; auto it = groupedVars.find(position); if (it != groupedVars.end()) for (auto &variable : it->second) retVariables.push_back(variable); return retVariables; } static void findDeclType(SgExpression *ex, varType &type, const string &toFind) { if (ex) { if (ex->symbol() && ex->symbol()->identifier() == toFind) { switch (ex->variant()) { case VAR_REF: if (type != ARRAY) type = SCALAR; break; case ARRAY_REF: type = ARRAY; break; case INT_VAL: case FLOAT_VAL: case DOUBLE_VAL: case BOOL_VAL: case CHAR_VAL: case STRING_VAL: case CONST_REF: type = CONST; break; case COMM_LIST: break; default: type = ANOTHER; break; } } findDeclType(ex->lhs(), type, toFind); findDeclType(ex->rhs(), type, toFind); } } void CommonBlock::addVariables(SgFile *file, SgStatement *function, const vector> &newVariables) { for (auto &varPair : newVariables) { vector allDecls; declaratedInStmt(varPair.first, &allDecls); varType type = ANOTHER; for (auto& decl : allDecls) for (int i = 0; i < 3; ++i) findDeclType(decl->expr(i), type, varPair.first->identifier()); Variable *exist = hasVariable(varPair.first, type, varPair.second); if (exist) exist->addUse(file, function, varPair.first); else { variables.push_back(new Variable(file, function, varPair.first, string(varPair.first->identifier()), type, varPair.second)); auto it = groupedVars.find(varPair.second); if (it == groupedVars.end()) it = groupedVars.insert(it, make_pair(varPair.second, vector())); it->second.push_back(variables.back()); } } } void CommonBlock::print(FILE *fileOut) const { fprintf(fileOut, " [POSITION], [VARIABLE NAME], [TYPE]: \n"); for (auto &var: variables) { var->print(fileOut); fprintf(fileOut, " USE in [FILE, FUNC / BLOCK_DATA]:"); for (auto &use : var->getAllUse()) fprintf(fileOut, " [%s, %s]", use.getFileName().c_str(), use.isBlockDataUse() ? ("BD_" + use.getFunctionName()).c_str() : ("F_" + use.getFunctionName()).c_str()); fprintf(fileOut, "\n"); } } DIST::Array* CommonBlock::getFirstSynonym(DIST::Array* array) const { if (array->GetLocation().first != DIST::l_COMMON) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& var : variables) { if (var->getName() == array->GetShortName()) { int pos = var->getPosition(); auto it = groupedVars.find(pos); if (it == groupedVars.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (it->second.size() == 1) return array; else { const string currFile = current_file->filename(); auto s = it->second[0]->getSymbol(); if (SgFile::switchToFile(it->second[0]->getDeclarated()->fileName()) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); string arrayName = string(s->identifier()); DIST::Array* firstArray = getArrayFromDeclarated(declaratedInStmt(s), arrayName); checkNull(firstArray, convertFileName(__FILE__).c_str(), __LINE__); if (SgFile::switchToFile(currFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return firstArray; } } } printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } // END of CommonBlock:: void groupDeclarations(SgFile *file) { for (int i = 0; i < file->numberOfFunctions(); ++i) { SgStatement *func = file->functions(i); SgStatement *lastNode = func->lastNodeOfStmt(); map, vector>> refs; vector toDel; for (auto st = func; st != lastNode; st = st->lexNext()) { if (isSgExecutableStatement(st)) break; if (st->variant() == VAR_DECL) { auto varDecl = isSgVarDeclStmt(st); SgExpression *varList = varDecl->varList(); int count = 0; for (auto lst = varList; lst; lst = lst->rhs()) count++; vector notMoved; int countOfMoved = 0; for (auto lst = varList; lst; lst = lst->rhs()) { SgExpression *var = lst->lhs(); if (var->variant() == VAR_REF) { auto type = var->symbol()->type(); if (type && isSgArrayType(type) == NULL && type->variant() != T_STRING) { countOfMoved++; refs[type].second.push_back(var); SgStatement *prev = st->lexPrev(); while (prev && prev->variant() == SPF_ANALYSIS_DIR) { refs[type].first.push_back(prev->extractStmt()); prev = st->lexPrev(); } } else notMoved.push_back(var); } else notMoved.push_back(var); } if (countOfMoved != count) { if (countOfMoved != 0) { SgExpression *varList = new SgExpression(EXPR_LIST); SgExpression *pVar = varList; for (int z = 0; z < notMoved.size(); z++) { pVar->setLhs(notMoved[z]); if (z != notMoved.size() - 1) { pVar->setRhs(new SgExpression(EXPR_LIST)); pVar = pVar->rhs(); } } st->setExpression(0, *varList); } } else toDel.push_back(st); } } for (auto st = func; st != lastNode; st = st->lexNext()) { if (isSgExecutableStatement(st->lexNext())) { for (auto &newDecl : refs) { SgVarDeclStmt *newDeclSt = newDecl.second.second[0]->symbol()->makeVarDeclStmt(); for (int z = 1; z < newDecl.second.second.size(); ++z) newDeclSt->addVar(*newDecl.second.second[z]); st->insertStmtAfter(*newDeclSt, *func); for (auto &spf : newDecl.second.first) st->insertStmtAfter(*spf, *func); } break; } } //TODO: move comments for (auto &elem : toDel) elem->deleteStmt(); } } bool ifSymbolExists(SgFile *file, const string &symbName) { if (SgFile::switchToFile(file->filename()) != -1) { SgSymbol *symb = file->firstSymbol(); while (symb) { if (symb->identifier() == symbName) return true; symb = symb->next(); } } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return false; } int checkSymbNameAndCorrect(const string& symbName, int complite) { set existedSymbols; //if (existedSymbols.size() == 0) { SgFile* oldFile = current_file; for (int i = 0; i < CurrentProject->numberOfFiles(); ++i) { SgFile* file = &(CurrentProject->file(i)); SgSymbol* s = file->firstSymbol(); while (s) { existedSymbols.insert(s->identifier()); s = s->next(); } } if (SgFile::switchToFile(oldFile->filename()) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } string base = symbName; int retNum = complite; while (existedSymbols.find(base + std::to_string(retNum)) != existedSymbols.end()) retNum++; //existedSymbols.insert(retName); return retNum; } string checkSymbNameAndCorrect(const string& symbName, const string complite) { set existedSymbols; //if (existedSymbols.size() == 0) { string oldFileName = current_file->filename(); for (int i = 0; i < CurrentProject->numberOfFiles(); ++i) { SgFile* file = &(CurrentProject->file(i)); SgSymbol* s = file->firstSymbol(); while (s) { existedSymbols.insert(s->identifier()); s = s->next(); } } if (SgFile::switchToFile(oldFileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } string retName = symbName; while (existedSymbols.find(retName) != existedSymbols.end()) retName += complite; //existedSymbols.insert(retName); return retName; } const CommonBlock* isArrayInCommon(const map &commonBlocks, const DIST::Array *array) { for (auto &commonBlockPair : commonBlocks) for (auto &variable : commonBlockPair.second->getVariables()) if (variable->getName() == array->GetShortName() && variable->getType() == ARRAY && array->GetLocation().first == DIST::l_COMMON) return commonBlockPair.second; return NULL; } static void fillArraysFromDirsRec(SgExpression *ex, vector &toAdd) { if (ex) { if (ex->variant() == ARRAY_REF) { auto attributes = getAttributes(ex, { ARRAY_REF }); toAdd.insert(toAdd.end(), attributes.begin(), attributes.end()); } if (ex->lhs()) fillArraysFromDirsRec(ex->lhs(), toAdd); if (ex->rhs()) fillArraysFromDirsRec(ex->rhs(), toAdd); } } vector fillArraysFromDir(Statement *st) { vector retVal; for (int z = 0; z < 3; ++z) fillArraysFromDirsRec(st->GetOriginal()->lexPrev()->expr(z), retVal); return retVal; } template objT& getObjectForFileFromMap(const char *fileName, map &mapObject) { auto it = mapObject.find(fileName); if (it == mapObject.end()) it = mapObject.insert(it, std::make_pair(fileName, objT())); return it->second; } template vector& getObjectForFileFromMap(const char *fileName, map>&); template PredictorStats& getObjectForFileFromMap(const char *fileName, map&); void printSymbolTable(SgFile *file, string filter, const set& vars) { for (auto s = file->firstSymbol(); s; s = s->next()) { if (vars.size() != 0) if (vars.find(s->variant()) == vars.end()) continue; auto t = s->type(); bool need = true; if (filter != "") if (filter != s->identifier()) need = false; if (need) { int line = s->scope() ? s->scope()->lineNumber() : -1; printf("[%d] '%s' type %d ('%s'), location %d line, variant %d, addr %p\n", s->id(), s->identifier(), t ? t->variant() : -1, t ? tag[t->variant()] : "", line, s->variant(), s->thesymb); } } } static bool checkAdd(const int var, const set &additional) { if (additional.size()) { if (additional.find(var) == additional.end()) return true; else return false; } else return true; } SgStatement* getFuncStat(SgStatement *st, const set additional) { if (!st) return NULL; SgStatement *iterator = st; while (iterator && !isSgProgHedrStmt(iterator) && checkAdd(iterator->variant(), additional)) iterator = iterator->controlParent(); if (!iterator) checkNull(iterator, convertFileName(__FILE__).c_str(), __LINE__); return iterator; } SgStatement* duplicateProcedure(SgStatement *toDup, const string *newName, bool withAttributes, bool withComment, bool withSameLines, bool dontInsert) { if (toDup == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (isSgProgHedrStmt(toDup) == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* global = current_file->firstStatement(); if (global->variant() != GLOBAL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgSymbol* orig = toDup->symbol(); SgSymbol* copied = &orig->copySubprogram(*global); //XXX: remove all extra functions if (global->lexNext()->symbol()->identifier() != string(copied->identifier())) { vector toDel; SgStatement* st = global->lexNext(); if (!isSgProgHedrStmt(st)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); while (st) { if (st->symbol() == copied) break; toDel.push_back(st); st = st->lastNodeOfStmt()->lexNext(); } if (st == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (!isSgProgHedrStmt(st)) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (st->symbol()->identifier() != string(copied->identifier())) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& elem : toDel) elem->extractStmt(); if (global->lexNext()->symbol()->identifier() != string(copied->identifier())) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } //move SgStatement* toMove = NULL; if (dontInsert) toMove = global->lexNext()->extractStmt(); else { if (toDup->controlParent()) { toMove = global->lexNext()->extractStmt(); toDup->insertStmtBefore(*toMove, *toDup->controlParent()); } else toMove = global->lexNext(); } //change name if (newName) copied->changeName(newName->c_str()); // set line numbers, pointer to attributes, comments and unparseIgnore status for (auto origStat = toDup, copyStat = toMove; origStat != toDup->lastNodeOfStmt()->lexNext(); origStat = origStat->lexNext(), copyStat = copyStat->lexNext()) { if (copyStat->variant() != origStat->variant()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (withSameLines) { copyStat->setlineNumber(origStat->lineNumber()); BIF_FILE_NAME(copyStat->thebif) = BIF_FILE_NAME(origStat->thebif); } if (withAttributes) if (origStat->numberOfAttributes() > 0) copyStat->addAttributeTree(origStat->getAttribute(0)); if (withComment) { if (origStat->comments()) copyStat->setComments(origStat->comments()); } copyStat->setUnparseIgnore(origStat->getUnparseIgnore()); } return toMove; } SgExpression* makeExprList(const vector& items, bool withSort) { SgExpression* list = NULL; if (items.size() == 0) return list; list = new SgExpression(EXPR_LIST); vector newItems; if (withSort) { multimap sorted; int tmpVal = 0; for (auto& elem : items) { if (elem->variant() == VAR_REF || elem->variant() == ARRAY_REF || elem->variant() == CONST_REF) sorted.insert(make_pair(elem->unparse(), elem)); else if (elem->lhs() && elem->lhs()->variant() == VAR_REF || elem->lhs()->variant() == ARRAY_REF) sorted.insert(make_pair(elem->lhs()->unparse(), elem)); else sorted.insert(make_pair(std::to_string(tmpVal++), elem)); } for (auto& elem : sorted) newItems.push_back(elem.second); std::reverse(newItems.begin(), newItems.end()); } else newItems = items; for (int z = 0; z < newItems.size(); ++z) { if (z == 0) list->setLhs(newItems[z]); else { SgExpression* tmp = new SgExpression(EXPR_LIST); tmp->setLhs(newItems[z]); tmp->setRhs(list); list = tmp; } } return list; } static bool sortByName(const pair& l, const pair& r) { return string(l.first->identifier()) < r.first->identifier(); } //if curr == NULL -> no insertion //all vars in sIn must have the same type SgStatement* makeDeclaration(SgStatement* curr, const vector& sIn, vector* inits) { if (sIn.size() == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* place = curr; SgStatement* scope = NULL; vector> s; if (place) { //check same type map>> groups; for (auto& toDec : sIn) { string newDecl = makeDeclaration(NULL, { toDec })->unparse(); auto it = newDecl.find("::"); if (it == string::npos) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); groups[newDecl.substr(0, it)][toDec->identifier()].push_back(toDec); } if (groups.size() > 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); while (isSgProgHedrStmt(place) == NULL && place->variant() != BLOCK_DATA && place->variant() != MODULE_STMT) place = place->controlParent(); scope = place; set declared; while (isSgExecutableStatement(place) == NULL && place != scope->lastNodeOfStmt()) { if (place->variant() == VAR_DECL || place->variant() == VAR_DECL_90) { SgExpression* ex = place->expr(0); while (ex) { if (ex->lhs() && ex->lhs()->symbol()) declared.insert(ex->lhs()->symbol()->identifier()); ex = ex->rhs(); } } place = place->lexNext(); } for (int z = 0; z < sIn.size(); ++z) if (declared.find(sIn[z]->identifier()) == declared.end()) s.push_back(make_pair(sIn[z], (inits ? (*inits)[z] : NULL))); } else { for (int z = 0; z < sIn.size(); ++z) s.push_back(make_pair(sIn[z], (inits ? (*inits)[z] : NULL))); } if (s.size() == 0) return NULL; sort(s.begin(), s.end(), sortByName); SgVarDeclStmt* decl = s[0].first->makeVarDeclStmt(); if (s[0].second) decl->expr(0)->setLhs(new SgExpression(ASSGN_OP, new SgVarRefExp(s[0].first), s[0].second)); for (int z = 1; z < s.size(); ++z) { auto tmpDecl = s[z].first->makeVarDeclStmt(); if (s[z].second) decl->addVar(*new SgExpression(ASSGN_OP, new SgVarRefExp(s[z].first), s[z].second)); else decl->addVar(*tmpDecl->expr(0)->lhs()); } if (place) { decl->setFileName(place->fileName()); decl->setFileId(place->getFileId()); decl->setProject(place->getProject()); decl->setlineNumber(getNextNegativeLineNumber()); //decl->setlineNumber(place->lineNumber()); place->insertStmtBefore(*decl, *scope); } decl->setVariant(VAR_DECL_90); return decl; } //vars in 'symbolsToDeclare' may be various type //TODO add inits parameter vector makeDeclaration(const vector& symbolsToDeclare, SgStatement* where, vector* inits) { vector allDecls; map>> groups; for (auto& toDec : symbolsToDeclare) { string newDecl = makeDeclaration(NULL, vector { toDec })->unparse(); auto it = newDecl.find("::"); if (it == string::npos) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); groups[newDecl.substr(0, it)][toDec->identifier()].push_back(toDec); } for (auto& toDecls : groups) { vector unitedList; for (auto& elem : toDecls.second) unitedList.push_back(elem.second[0]); allDecls.push_back(makeDeclaration(where, unitedList)); } return allDecls; } int getNextFreeLabel() { PTR_LABEL lab; set used; for (lab = PROJ_FIRST_LABEL(); lab; lab = LABEL_NEXT(lab)) used.insert(LABEL_STMTNO(lab)); for (int z = 1; z < 99999; ++z) if (used.find(z) == used.end()) return z; return -1; } static void recFillUsedVars(SgExpression *exp, map &vars) { if (exp) { if (exp->symbol() && (exp->variant() == VAR_REF || exp->variant() == ARRAY_REF || exp->variant() == CONST_REF) && !(exp->symbol()->attributes() & PRIVATE_BIT)) { const auto key = exp->symbol()->identifier(); if (vars.find(key) == vars.end()) vars.insert(make_pair(key, exp->symbol())); } recFillUsedVars(exp->lhs(), vars); recFillUsedVars(exp->rhs(), vars); } } static inline void fillUsedVars(SgStatement *st, map &vars) { if (st) { for (int i = 0; i < 3; ++i) { SgExpression *exp = st->expr(i); recFillUsedVars(exp, vars); } } } static inline void joinMaps(map &map1, const map &map2, const map &exept = map()) { for (auto &pair : map2) if (exept.find(pair.first) == exept.end() && map1.find(pair.first) == map1.end()) map1.insert(pair); } void fillVisibleInUseVariables(SgStatement *useSt, map &vars) { if (useSt) { if (useSt->variant() == USE_STMT) { bool only = false; map localVars; // local module variables map useVars; // variables from other modules map renamedVas; // renamed variables map originVars; // origin variables names in USE_STAT // check USE_STAT // fill from ONLY_NODE and RENAME_NODE SgExpression *ex = useSt->expr(0); if (ex && ex->variant() == ONLY_NODE) { only = true; ex = ex->lhs(); } for (auto exI = ex; exI; exI = exI->rhs()) { if (exI->lhs()->variant() == RENAME_NODE) { SgExpression *ren = exI->lhs(); if (ren->lhs()->symbol() && ren->rhs() && ren->rhs()->symbol()) { if (renamedVas.find(ren->lhs()->symbol()->identifier()) == renamedVas.end()) renamedVas.insert(make_pair(ren->lhs()->symbol()->identifier(), ren->lhs()->symbol())); if (originVars.find(ren->rhs()->symbol()->identifier()) == originVars.end()) originVars.insert(make_pair(ren->rhs()->symbol()->identifier(), ren->rhs()->symbol())); } else if (only && ren->lhs()->symbol()) { if (renamedVas.find(ren->lhs()->symbol()->identifier()) == renamedVas.end()) renamedVas.insert(make_pair(ren->lhs()->symbol()->identifier(), ren->lhs()->symbol())); } } } if (!only) { // check module const string modName(useSt->symbol()->identifier()); vector modules; findModulesInFile(useSt->getFile(), modules); bool found = false; for (auto i = 0; i < modules.size(); ++i) { if (modName == modules[i]->symbol()->identifier()) { found = true; vector useStats; for (SgStatement *st = modules[i]->lexNext(); st != modules[i]->lastNodeOfStmt(); st = st->lexNext()) { if (st->variant() == USE_STMT) useStats.push_back(st); else if (st->variant() == CONTAINS_STMT) break; else fillUsedVars(st, localVars); } for (auto &useSt : useStats) { map visibleVars; fillVisibleInUseVariables(useSt, visibleVars); joinMaps(useVars, visibleVars); } break; } } if (!found) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } // fill vars // TODO: check renaming joinMaps(vars, useVars, originVars); joinMaps(vars, localVars, originVars); joinMaps(vars, renamedVas); } } } Variable::Variable(SgFile* file, SgStatement* function, SgSymbol* symbol, const std::string& name, const varType type, const int position) : symbol(symbol), name(name), type(type), position(position) { declPace = declaratedInStmt(symbol); allUse.push_back(CommonVariableUse(file, function, symbol)); } string preprocDataString(string data, bool full) { string ret = ""; for (int z = 0; z < data.size(); ++z) { if (data[z] == '\t') data[z] = ' '; else if (data[z] == '\r') data[z] = ' '; } auto it = data.find("DATA"); if (it == string::npos) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); else it += 4; if (data[it] != ' ') printInternalError(convertFileName(__FILE__).c_str(), __LINE__); else it++; if (full) ret = "DATA "; int i = it; while (i != data.size()) { if (data[i] != ' ') ret += data[i++]; else i++; } return ret; } map splitData(const set& dataStats) { map result; for (auto& dataV : dataStats) { char* value = dataV->thellnd->entry.string_val; string dataS(value); convertToUpper(dataS); dataS = preprocDataString(dataS, false); convertToLower(dataS); string currS = ""; string currV = ""; int startV = -1; for (int z = 0; z < dataS.size(); ++z) { if (startV == -1) { if (dataS[z] == '/') startV = 0; else if (dataS[z] != ' ' && dataS[z] != ',') currS += dataS[z]; } else if (startV == 0) { if (dataS[z] == '/') { startV = -1; result[currS] = currV; currS = currV = ""; } else if (dataS[z] != ' ') currV += dataS[z]; } } } return result; } void extractComments(SgStatement* where, const string& what) { if (BIF_CMNT(where->thebif) && CMNT_STRING(BIF_CMNT(where->thebif))) { char* str = CMNT_STRING(BIF_CMNT(where->thebif)); string source(str); removeSubstrFromStr(source, what.c_str()); sprintf(str, "%s", source.c_str()); } } void getVariables(SgExpression* ex, set& variables, const set variants) { if (ex) { if (variants.find(ex->variant()) != variants.end()) variables.insert(OriginalSymbol(ex->symbol())->identifier()); getVariables(ex->rhs(), variables, variants); getVariables(ex->lhs(), variables, variants); } } void getVariables(SgExpression* ex, set& variables, const set variants) { if (ex) { if (variants.find(ex->variant()) != variants.end()) variables.insert(OriginalSymbol(ex->symbol())); getVariables(ex->rhs(), variables, variants); getVariables(ex->lhs(), variables, variants); } } template set getAllVariables(SgStatement* stFrom, SgStatement* stTo, const set& variants) { set vars; for (auto stmt = stFrom; stmt != stTo; stmt = stmt->lexNext()) for (int i = 0; i < 3; ++i) getVariables(stmt->expr(i), vars, variants); return vars; } template set getAllVariables(SgStatement* stFrom, SgStatement* stTo, const set& variants); template set getAllVariables(SgStatement* stFrom, SgStatement* stTo, const set& variants); void shiftLines(SgProject* project, bool print) { map shifts; //shift lines if modules included const string shiftInfo = "!SPF NUM FILES"; for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); const string fileN = file->filename(); int shiftN = 0; for (auto st = file->firstStatement(); st; st = st->lexNext()) { if (st->comments()) { string comms = st->comments(); auto it = comms.find(shiftInfo); if (it != string::npos) { it += shiftInfo.size() + 1; if (sscanf(comms.c_str() + it, "%d", &shiftN) == -1) { __spf_print(print, "comm %s, shifted %s\n", comms.c_str(), comms.c_str() + it); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } break; } } } if (shiftN == 0) continue; shifts[fileN] = shiftN + 1; // with comment !SPF NUM FILES __spf_print(print, " shift by %d for %s\n", shiftN, fileN.c_str()); } for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); for (SgStatement* st = file->firstStatement()->lexNext(); st; st = st->lexNext()) { string currF = st->fileName(); auto it = shifts.find(currF); if (it != shifts.end() && file->filename() == currF) st->setlineNumber(st->lineNumber() - it->second); } } } SgProject* createProject(const char* proj_name, vector& parallelRegions, vector& subs_parallelRegions, map>& hiddenData, map& filesNameWithoutExt, map>& moduleUsesByFile, map& moduleDecls, map>>& exctactedModuleStats, bool printSymbTable) { Statement::setSapforRegime(); Statement::deactiveConsistentchecker(); sortFilesBySize(proj_name); SgProject* project = new SgProject(proj_name); addNumberOfFileToAttribute(project); if (printSymbTable) { for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); printf("===== TABLE FOR FILE %s\n", file->filename()); printSymbolTable(file, ""); } exit(0); } parallelRegions.push_back(new ParallelRegion(0, "DEFAULT")); subs_parallelRegions.push_back(new ParallelRegion(0, "DEFAULT")); Statement::activeConsistentchecker(); Statement::activeDeprecatedchecker(); //hide duplicated functions for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); //file->unparsestdout(); const string fileN = file->filename(); auto first = file->firstStatement(); SgStatement* lastValid = NULL; const string toFind = "!SPF SHADOW FILES"; for (SgStatement* st = first->lexNext(), *stPrev = first; st; st = st->lexNext(), stPrev = stPrev->lexNext()) { if (st->comments()) { string comm(st->comments()); if (comm.find(toFind) != string::npos) { if (st->variant() == CONTROL_END) { extractComments(st, toFind); lastValid = st; } else lastValid = stPrev; break; } } } if (lastValid) { vector toExtract; auto st = lastValid->lexNext(); while (st) { toExtract.push_back(st); st = st->lastNodeOfStmt(); st = st->lexNext(); } __spf_print(1, "hidden data for file '%s'\n", file->filename()); set validVars = { PROG_HEDR, FUNC_HEDR, PROC_HEDR, BLOCK_DATA, MODULE_STMT }; for (auto& elem : toExtract) { int var = elem->variant(); if (validVars.find(var) == validVars.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); __spf_print(1, " [%s, %d]\n", elem->fileName(), elem->lineNumber()); hiddenData[fileN].push_back(elem->extractStmt()); } lastValid->setLexNext((SgStatement*)NULL); } } //hide excluded modules const set excludedMods = getExcludedModules(); for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); const string fileN = file->filename(); auto first = file->firstStatement(); SgStatement* lastValid = NULL; vector toExtract; for (SgStatement* st = first->lexNext(); st; st = st->lexNext()) { if (st->variant() == USE_STMT) { string name = st->symbol()->identifier(); if (excludedMods.find(name) != excludedMods.end()) { SgStatement* before = st->lexNext(); do { if (before->variant() == USE_STMT) { if (excludedMods.find(before->symbol()->identifier()) != excludedMods.end()) { before = before->lexNext(); continue; } } break; } while (true); exctactedModuleStats[fileN][before].push_back(st); toExtract.push_back(st); } } } for (auto& elem : toExtract) elem->extractStmt(); } //dump symbol table and symbol use /*printSymbolTable(current_file); for (auto st = current_file->firstStatement()->lexNext(); st; st = st->lexNext()) { if (st->variant() != MODULE_STMT && isSgProgHedrStmt(st) == NULL) { set refs; for (int z = 0; z < 3; ++z) if (st->expr(z)) fillAllSymbs(st->expr(z), refs); if (refs.size()) { printf("FOR STATEMENT ON LINE %d:\n", st->lineNumber()); st->unparsestdout(); printf("refs ids:"); for (auto& elem : refs) printf(" %d (%s)", elem->id(), elem->identifier()); printf(";\n\n"); } } }*/ set filesInProj; //preprocess module includes for (int z = 0; z < project->numberOfFiles(); ++z) filesInProj.insert((project->file(z)).filename()); //check main unit findMainUnit(project, SPF_messages); set globalFunctions; for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); string name = OnlyName(file->filename()); if (filesNameWithoutExt.find(name) == filesNameWithoutExt.end()) filesNameWithoutExt[name] = 1; else filesNameWithoutExt[name]++; fillModuleUse(file, moduleUsesByFile, moduleDecls); int funcCount = file->numberOfFunctions(); for (int k = 0; k < funcCount; ++k) { auto func = file->functions(k); if (func->controlParent()->variant() == GLOBAL) globalFunctions.insert(func->symbol()->identifier()); } } filterModuleUse(moduleUsesByFile, moduleDecls); //shift lines if modules included shiftLines(project); map> functions; for (int z = 0; z < project->numberOfFiles(); ++z) fillFunctionInfo(&(project->file(z)), functions); set needToResolve; for (auto& func : functions) if (func.second.size() > 1) needToResolve.insert(func.first); for (int z = 0; z < project->numberOfFiles(); ++z) resolveFunctionCalls(&(project->file(z)), needToResolve, functions); for (int z = 0; z < project->numberOfFiles(); ++z) correctModuleProcNames(&(project->file(z)), globalFunctions); for (int z = 0; z < project->numberOfFiles(); ++z) removeExecutableFromModuleDeclaration(&(project->file(z)), filesInProj, hiddenData[project->file(z).filename()]); for (int z = 0; z < project->numberOfFiles(); ++z) { SgFile* file = &(project->file(z)); correctModuleSymbols(file); //file->unparsestdout(); } if (detectMpiCalls(project, SPF_messages)) { sharedMemoryParallelization = 1; keepDvmDirectives = 0; ignoreIO = 1; parallizeFreeLoops = 0; } return project; } static bool isIntrinsic(SgType* base) { switch (base->variant()) { case T_INT: case T_FLOAT: case T_BOOL: case T_DOUBLE: case T_COMPLEX: case T_DCOMPLEX: case T_CHAR: return true; default: break; } return false; } bool isArrayType(SgType* type) { if (type) { SgType* base = type->baseType(); if (base && type->variant() != T_STRING && base->variant() != T_STRING && (IS_INTRINSIC_TYPE(base) || isIntrinsic(base))) return true; } return false; } bool isArrayRef(SgExpression* ex) { if (ex && ex->variant() == ARRAY_REF) { SgArrayRefExp* arrayRef = isSgArrayRefExp(ex); if (arrayRef) if (isArrayType(ex->symbol()->type())) { auto type = isSgArrayType(ex->symbol()->type()); if (type && type->dimension()) return true; } } return false; } bool isStringArrayType(SgType* type) { if (type) { SgType* base = type->baseType(); if (base && (type->variant() == T_STRING || base->variant() == T_STRING)) return true; } return false; } void moveLabelBefore(SgStatement* st, SgStatement* next) { SgLabel* lab = next ? next->label() : st->label(); if (lab) { SgStatement* cont = new SgContinueStmt(); cont->setLabel(*lab); if (next) next->deleteLabel(true); else st->deleteLabel(true); if (next) { cont->setFileName(next->fileName()); cont->setProject(next->getProject()); cont->setFileId(next->getFileId()); cont->setlineNumber(next->lineNumber()); } else { cont->setFileName(st->fileName()); cont->setProject(st->getProject()); cont->setFileId(st->getFileId()); cont->setlineNumber(getNextNegativeLineNumber()); } st->insertStmtBefore(*cont, *st->controlParent()); } } bool isEqSymbols(SgSymbol* sym1, SgSymbol* sym2) { if (!sym1 || !sym2) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return string(OriginalSymbol(sym1)->identifier()) == string(OriginalSymbol(sym2)->identifier()); } set getAllFilesInProject() { set res; const string currId = current_file->filename(); for (int z = 0; z < CurrentProject->numberOfFiles(); ++z) res.insert(CurrentProject->file(z).filename()); if (SgFile::switchToFile(currId) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return res; } void LogIftoIfThen(SgStatement* stmt) { SgControlEndStmt* control = new SgControlEndStmt(); stmt->setVariant(IF_NODE); stmt->lexNext()->insertStmtAfter(*control, *stmt); if (stmt->numberOfAttributes(OMP_MARK) > 0) control->addAttribute(OMP_MARK); } void removeSpecialCommentsFromProject(SgFile* file) { //remove SAPFOR comment with version SgStatement* stF = file->firstStatement()->lexNext(); while (stF) { if (stF && stF->comments()) { string oldComment(stF->comments()); auto it = oldComment.find("! *** generated by SAPFOR"); if (it != string::npos) { auto endIt = oldComment.find("! *** generated by SAPFOR", it + 1); endIt = oldComment.find("\n", (endIt != string::npos) ? endIt : it); string newComment = oldComment.substr(0, it) + oldComment.substr(endIt + 1); stF->delComments(); if (newComment != "") stF->setComments(newComment.c_str()); if (genVersionDone.find(file) != genVersionDone.end()) genVersionDone.erase(file); } } stF = stF->lexNext(); } } //TODO: for gen_block and other variations, and redistributions dirs void getMaxMinBlockDistribution(SgFile* file, pair& min_max) { SgStatement* st = file->firstStatement(); while (st) { if (isDVM_stat(st)) { if (st->variant() == DVM_DISTRIBUTE_DIR || st->variant() == DVM_VAR_DECL) { for (int z = 0; z < 3; ++z) { SgExpression* ex = st->expr(z); queue q; if (ex) { q.push(ex); int blockCount = 0; while (q.size()) { ex = q.front(); q.pop(); if (ex->rhs()) q.push(ex->rhs()); if (ex->lhs()) q.push(ex->lhs()); if (ex->variant() == BLOCK_OP) blockCount++; } if (blockCount) { if (min_max == make_pair(-1, -1)) min_max = make_pair(blockCount, blockCount); else { min_max.first = std::min(min_max.first, blockCount); min_max.second = std::max(min_max.second, blockCount); } } } } } } st = st->lexNext(); } } //TODO: need to add to includes void addPrivatesToArraysFromGUI(SgFile* file, const map, pair>& declaredArrays, const map& distrStateFromGUI) { map> added; for (auto& arrayPair : declaredArrays) { DIST::Array* array = arrayPair.second.first; string key = array->GetIndepUniqName(); auto it = distrStateFromGUI.find(key); if (it == distrStateFromGUI.end()) continue; if (it->second != DIST::NO_DISTR) continue; for (auto& decl : array->GetDeclInfoWithSymb()) { auto& place = decl.first; const auto& symb = decl.second->GetOriginal(); if (place.first != file->filename()) continue; SgStatement* declSt = SgStatement::getStatementByFileAndLine(place.first, place.second); checkNull(declSt, convertFileName(__FILE__).c_str(), __LINE__); added[declSt].insert(symb); } } for (auto& toInsert : added) { vector list; for (auto& elem : toInsert.second) list.push_back(new SgVarRefExp(elem)); SgStatement* op = new SgStatement(SPF_ANALYSIS_DIR); op->setExpression(0, new SgExpression(SPF_PROCESS_PRIVATE_OP, makeExprList(list))); toInsert.first->insertStmtBefore(*op, *toInsert.first->controlParent()); } }