#include "../Utils/leak_detector.h" #include #include #include #include #include #include #include #include #include #include "dvm.h" #include "../Sapfor.h" #include "../GraphLoop/graph_loops.h" #include "../GraphCall/graph_calls_func.h" #include "../SageAnalysisTool/depInterfaceExt.h" #include "../Utils/SgUtils.h" #include "../Utils/errors.h" #include "directive_parser.h" #include "../ExpressionTransform/expr_transform.h" #include "../LoopAnalyzer/loop_analyzer.h" #include "../DirectiveProcessing/directive_omp_parser.h" using std::string; using std::wstring; using std::vector; using std::map; using std::set; using std::pair; using std::tuple; static void addToattribute(SgStatement *toAttr, SgStatement *curr, const int variant) { // move SgStatement to attribute SgStatement *toAdd = new SgStatement(toAttr->variant(), NULL, toAttr->symbol(), toAttr->expr(0), toAttr->expr(1), toAttr->expr(2)); toAdd->setlineNumber(toAttr->lineNumber()); toAdd->setLocalLineNumber(SPF_USER_DIR); curr->addAttribute(variant, toAdd, sizeof(SgStatement)); //copy comments to st if (toAttr->comments() && variant != SPF_END_PARALLEL_REG_DIR && variant != SPF_PARALLEL_REG_DIR) { string comments(toAttr->comments()); if (curr->comments()) comments += "\n" + string(curr->comments()); if (comments.size() != 0) curr->setComments(comments.c_str()); } } void fillVars(SgExpression* exp, const set& types, set& identifierList, vector& funcCalls) { if (exp) { if (exp->variant() == FUNC_CALL) funcCalls.push_back(exp); if (types.find(exp->variant()) != types.end()) { if (exp->symbol()) identifierList.insert(OriginalSymbol(exp->symbol())->identifier()); else if (exp->variant() == DDOT) identifierList.insert(exp->symbol()->identifier()); // BAD solution } fillVars(exp->lhs(), types, identifierList, funcCalls); fillVars(exp->rhs(), types, identifierList, funcCalls); } } void fillVars(SgExpression *exp, const set &types, set &identifierList, vector &funcCalls) { if (exp) { if (exp->variant() == FUNC_CALL) funcCalls.push_back(exp); if (types.find(exp->variant()) != types.end()) { if (exp->symbol()) identifierList.insert(OriginalSymbol(exp->symbol())); else if (exp->variant() == DDOT) identifierList.insert((SgSymbol*)exp); // BAD solution } fillVars(exp->lhs(), types, identifierList, funcCalls); fillVars(exp->rhs(), types, identifierList, funcCalls); } } static bool isPrivateVar(SgStatement *st, SgSymbol *symbol) { bool retVal = false; for (auto &data : getAttributes(st, set{ SPF_ANALYSIS_DIR })) { set privates; fillPrivatesFromComment(new Statement(data), privates); retVal = retVal || privates.find(symbol->identifier()) != privates.end(); if (retVal) break; } return retVal; } #define BAD_POSITION_FULL(ERR_TYPE, PLACE_E, PLACE_R, BEFORE_VAR_E, BEFORE_VAR_R, BEFORE_DO_E, BEFORE_DO_R, LINE) do { \ __spf_print(1, "bad directive position on line %d, it can be placed only %s %s %s\n", LINE, PLACE_E, BEFORE_VAR_E, BEFORE_DO_E); \ wstring messageE, messageR;\ __spf_printToLongBuf(messageE, L"bad directive position, it can be placed only %s %s %s", to_wstring(PLACE_E).c_str(), to_wstring(BEFORE_VAR_E).c_str(), to_wstring(BEFORE_DO_E).c_str()); \ __spf_printToLongBuf(messageR, R1, PLACE_R, BEFORE_VAR_R, BEFORE_DO_R); \ messagesForFile.push_back(Messages(ERR_TYPE, LINE, messageR, messageE, 1001)); \ } while(0) static SgStatement* skipDvmDirs(SgStatement *st) { while (isDVM_stat(st)) st = st->lexNext(); return st; } static void fillVarsSets(SgStatement *iterator, SgStatement *end, set &varDef, set &varUse) { for ( ;iterator != end; iterator = iterator->lexNext()) { vector funcCalls; if (iterator->variant() == PROC_STAT) {// TODO: procedures may have IN, INOUT, OUT parameters fillVars(iterator->expr(0), { ARRAY_REF, VAR_REF }, varDef, funcCalls); fillVars(iterator->expr(0), { ARRAY_REF, VAR_REF }, varUse, funcCalls); } else { if (iterator->variant() == ASSIGN_STAT || isSgExecutableStatement(iterator) == NULL) fillVars(iterator->expr(0), { ARRAY_REF, VAR_REF }, varDef, funcCalls); else fillVars(iterator->expr(0), { ARRAY_REF, VAR_REF }, varUse, funcCalls); fillVars(iterator->expr(1), { ARRAY_REF, VAR_REF }, varUse, funcCalls); fillVars(iterator->expr(2), { ARRAY_REF, VAR_REF }, varUse, funcCalls); if (iterator->variant() == FOR_NODE) { auto loop = isSgForStmt(iterator); varDef.insert(loop->doName()->identifier()); varUse.insert(loop->doName()->identifier()); } vector dummy; // TODO: functions may have IN, INOUT, OUT parameters for (auto &func : funcCalls) fillVars(func, { ARRAY_REF, VAR_REF }, varDef, dummy); } } } static bool checkCover(SgStatement* st, SgStatement* attributeStatement, const int coverLoops, vector& messagesForFile) { // COVER(VALUE) const int var = st->variant(); bool retVal = true; SgForStmt* forSt = (SgForStmt*)st; const int nestedCount = countPerfectLoopNest(forSt); if (coverLoops > nestedCount || coverLoops == 0) { __spf_print(1, "bad directive expression: expected %d nested loops on line %d but got %d on line %d\n", coverLoops, attributeStatement->lineNumber(), nestedCount, st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: expected %d nested loops on line %d but got %d", coverLoops, attributeStatement->lineNumber(), nestedCount); __spf_printToLongBuf(messageR, R77, coverLoops, attributeStatement->lineNumber(), nestedCount); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1043)); retVal = false; } return retVal; } static bool checkProcessPrivate(SgStatement* st, SgStatement* attributeStatement, const set& privates, vector& messagesForFile) { // PROCESS_PRIVATE(VAR) const int var = st->variant(); bool retVal = true; if (!isSgExecutableStatement(st)) { st = skipDvmDirs(st); SgStatement* iterator = st; SgStatement* end = st->lexNext(); set varDef, varUse; fillVarsSets(iterator, end, varDef, varUse); for (auto& privElemS : privates) { const string privElem = privElemS->GetOriginal()->identifier(); bool defCond = true; if (varDef.find(privElem) == varDef.end()) defCond = false; if (!defCond) { BAD_POSITION_FULL(ERROR, "before", RR1_1, "variable declaration", RR1_2, "", L" ", attributeStatement->lineNumber()); retVal = false; } } } else { BAD_POSITION_FULL(ERROR, "before", RR1_1, "variable declaration", RR1_2, "", L" ", attributeStatement->lineNumber()); retVal = false; } return retVal; } static bool checkPrivate(SgStatement *st, SgStatement *attributeStatement, const set &privates, vector &messagesForFile) { // PRIVATE(VAR) const int var = st->variant(); bool retVal = true; if (var == FOR_NODE) { st = skipDvmDirs(st); SgStatement *iterator = st; SgStatement *end = st->lastNodeOfStmt(); set varDef, varUse; set wrongPrivFromOmpParallel; fillVarsSets(iterator, end, varDef, varUse); for (auto& privElemS : privates) { const string privElem = privElemS->GetOriginal()->identifier(); bool defCond = true; bool useCond = true; if (varDef.find(privElem) == varDef.end()) defCond = false; if (varUse.find(privElem) == varUse.end()) useCond = false; if (!defCond && !useCond) { if (attributeStatement->localLineNumber() != SPF_OMP_DIR) { __spf_print(1, "variable '%s' is not used in loop on line %d\n", privElem.c_str(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not used in loop", to_wstring(privElem.c_str()).c_str()); __spf_printToLongBuf(messageR, R21, to_wstring(privElem.c_str()).c_str()); messagesForFile.push_back(Messages(WARR, attributeStatement->lineNumber(), messageR, messageE, 1002)); } else wrongPrivFromOmpParallel.insert(privElem); } else if (!defCond && useCond) { if (attributeStatement->localLineNumber() != SPF_OMP_DIR) { __spf_print(1, "variable '%s' is not changed in loop on line %d\n", privElem.c_str(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not changed in loop", to_wstring(privElem.c_str()).c_str()); __spf_printToLongBuf(messageR, R23, to_wstring(privElem.c_str()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1003)); retVal = false; } else wrongPrivFromOmpParallel.insert(privElem); } } if (wrongPrivFromOmpParallel.size()) // remove unnecessary { if (wrongPrivFromOmpParallel.size() == privates.size()) // remove all attributeStatement->expr(0)->lhs()->setLhs(NULL); else { SgExpression* list = attributeStatement->expr(0)->lhs()->lhs(); vector newList; for (auto ex = list; ex; ex = ex->rhs()) { string currV = ex->lhs()->symbol()->identifier(); if (wrongPrivFromOmpParallel.find(currV) == wrongPrivFromOmpParallel.end()) newList.push_back(ex->lhs()); } attributeStatement->expr(0)->lhs()->setLhs(makeExprList(newList)); } } } else { BAD_POSITION_FULL(ERROR, "before", RR1_1, "", L"", "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } return retVal; } static bool checkReduction(SgStatement *st, SgStatement *attributeStatement, const map> &reduction, vector &messagesForFile) { // REDUCTION(OP(VAR)) const int var = st->variant(); bool retVal = true; if (var == FOR_NODE) { SgStatement *iterator = st->lexNext(); SgStatement *end = st->lastNodeOfStmt(); set varDef; set varUse; fillVarsSets(iterator, end, varDef, varUse); for (auto &redElem : reduction) { for (auto &setElemS : redElem.second) { const string setElem = setElemS->GetOriginal()->identifier(); bool defCond = true; bool useCond = true; if (varDef.find(setElem) == varDef.end()) defCond = false; if (varUse.find(setElem) == varUse.end()) useCond = false; if (var == FOR_NODE && !defCond && !useCond) { __spf_print(1, "variable '%s' is not used in loop on line %d\n", setElem.c_str(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not used in loop", to_wstring(setElem.c_str()).c_str()); __spf_printToLongBuf(messageR, R22, to_wstring(setElem.c_str()).c_str()); messagesForFile.push_back(Messages(WARR, attributeStatement->lineNumber(), messageR, messageE, 1002)); } if (var == FOR_NODE && !defCond && useCond) { __spf_print(1, "variable '%s' is not changed in loop on line %d\n", setElem.c_str(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not changed in loop", to_wstring(setElem.c_str()).c_str()); __spf_printToLongBuf(messageR, R24, to_wstring(setElem.c_str()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1003)); retVal = false; } } } } else { BAD_POSITION_FULL(ERROR, "before", RR1_1, "", L"", "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } return retVal; } static bool checkReduction(SgStatement *st, SgStatement *attributeStatement, const map>> &reduction, vector &messagesForFile) { // REDUCTION(MIN/MAXLOC(VAR, ARRAY, CONST)) bool retVal = true; for (auto &redElem : reduction) { set vars; set arrs; set varsS; set arrsS; for (auto &setElem : redElem.second) { vars.insert(std::get<0>(setElem)); varsS.insert(std::get<0>(setElem)->GetOriginal()->identifier()); arrs.insert(std::get<1>(setElem)); arrsS.insert(std::get<1>(setElem)->GetOriginal()->identifier()); // CHECK ARRAY DECLARATION && DIMENTION SgSymbol *arraySymbol = std::get<1>(setElem)->GetOriginal(); SgStatement *declStatement = declaratedInStmt(arraySymbol); SgArrayType *arrayType = NULL; int count = std::get<2>(setElem); if (arraySymbol->type()) arrayType = isSgArrayType(arraySymbol->type()); if (arrayType) { const int dim = arrayType->dimension(); if (dim != 1) { __spf_print(1, "dimention of array '%s' is %d, but must be 1 on line %d\n", arraySymbol->identifier(), dim, attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"dimention of array '%s' is %d, but must be 1", to_wstring(arraySymbol->identifier()).c_str(), dim); __spf_printToLongBuf(messageR, R25, to_wstring(arraySymbol->identifier()).c_str(), dim); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1004)); retVal = false; } if (!arrayType->baseType()->equivalentToType(SgTypeInt())) { __spf_print(1, "type of array '%s' must be INTEGER on line %d\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"type of array '%s' but must be INTEGER", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R26, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1005)); retVal = false; } } else { __spf_print(1, "type of variable '%s' must be array on line %d\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"type of variable '%s' must be array", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R27, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1006)); retVal = false; } SgStatement *iterator = st; SgStatement *end = st; vector dimentions; while (iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR) iterator = iterator->controlParent(); while (iterator != end) { if (isSPF_stat(iterator) || isDVM_stat(iterator)) { iterator = iterator->lexNext(); continue; } if (!isSgExecutableStatement(iterator)) { for (SgExpression *exp = iterator->expr(0); exp; exp = exp->rhs()) if (exp->lhs()->symbol() == arraySymbol) for (SgExpression *list = exp->lhs()->lhs(); list; list = list->rhs()) dimentions.push_back(list->lhs()); if (dimentions.size()) { if (dimentions.size() != 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); int size; int err = CalculateInteger(dimentions[0], size); if (err != 0) { // Expression can not be computed __spf_print(1, "array size can't be computed on line %d\n", attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array size can't be computed"); __spf_printToLongBuf(messageR, R30); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1007)); retVal = false; } else if (size != count) { __spf_print(1, "size of array '%s' is %d, but you enter %d on line %d\n", arraySymbol->identifier(), size, count, attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"size of array '%s' is %d, but you enter %d", to_wstring(arraySymbol->identifier()).c_str(), size, count); __spf_printToLongBuf(messageR, R31, to_wstring(arraySymbol->identifier()).c_str(), size, count); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1008)); retVal = false; } break; } } else break; iterator = iterator->lexNext(); } } map> reductionVar; map> reductionArr; reductionVar[redElem.first] = vars; reductionArr[redElem.first] = arrs; retVal = checkReduction(st, attributeStatement, reductionVar, messagesForFile) && checkReduction(st, attributeStatement, reductionArr, messagesForFile); } return retVal; } static bool findSymbolInExpressionRec(SgExpression *exp, SgSymbol *s) { if (exp) { //if (exp->symbol() && string(exp->symbol()->identifier()) == s->identifier()) if (exp->symbol() && exp->symbol() == s) return true; return findSymbolInExpressionRec(exp->lhs(), s) || findSymbolInExpressionRec(exp->rhs(), s); } return false; } static bool findSymbolInStatement(SgStatement *st, SgSymbol *s) { if (!st || !s) return false; bool found = false; for (int i = 0; !found && i < 3; ++i) found = found || findSymbolInExpressionRec(st->expr(i), s); return found; } static bool checkParametersExpressionRec(SgStatement *st, SgStatement *attributeStatement, SgExpression *exp, vector &messagesForFile) { bool retVal = true; if (exp && exp->variant() == VAR_REF && exp->symbol()) { auto declStatement = declaratedInStmt(OriginalSymbol(exp->symbol()), NULL, false); // check all used modules in function auto moduleVar = false; vector useStats; fillUsedModulesInFunction(st, useStats); for (auto& useSt : useStats) { map visibleVars; fillVisibleInUseVariables(useSt, visibleVars); if (visibleVars.find(exp->symbol()->identifier()) != visibleVars.end()) moduleVar = true; } if (!declStatement && !moduleVar) { __spf_print(1, "Variable '%s' in %s clause must be declared at the same module in file '%s' on line %d.\n", exp->symbol()->identifier(), "PARAMETER", st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Variable '%s' in %s clause must be declared at the same module.", to_wstring(exp->symbol()->identifier()).c_str(), to_wstring("PARAMETER").c_str()); __spf_printToLongBuf(messageR, R168, to_wstring(exp->symbol()->identifier()).c_str(), to_wstring("PARAMETER").c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5004)); retVal = false; } } bool leftResult, rightResult; leftResult = rightResult = true; if (exp->lhs()) leftResult = checkParametersExpressionRec(st, attributeStatement, exp->lhs(), messagesForFile); if (exp->rhs()) rightResult = checkParametersExpressionRec(st, attributeStatement, exp->rhs(), messagesForFile); retVal = retVal && leftResult && rightResult; return retVal; } static bool checkParameter(SgStatement *st, SgStatement *attributeStatement, const vector> &assigns, vector &messagesForFile) { bool retVal = true; if (!isSgExecutableStatement(st)) { wstring messageE, messageR; __spf_print(1, "ANALYSIS directive with PARAMETER clause can be only at executable code section in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"ANALYSIS directive with PARAMETER clause can be only at executable code section."); __spf_printToLongBuf(messageR, R166, L"ANALYSIS", L"PARAMETER"); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5002)); retVal = false; } for (auto &assign : assigns) { auto assignVarExp = assign.first->GetOriginal(); auto assignVarVar = assignVarExp->variant(); if (!findSymbolInStatement(st, assignVarExp->symbol())) { __spf_print(1, "Variable '%s' in %s clause must be used in next statement in file '%s' on line %d.\n", assignVarExp->symbol()->identifier(), "PARAMETER", st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Variable '%s' in %s clause must be used in next statement.", to_wstring(assignVarExp->symbol()->identifier()).c_str(), to_wstring("PARAMETER").c_str()); __spf_printToLongBuf(messageR, R175, to_wstring(assignVarExp->symbol()->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1057)); retVal = false; } if (assignVarVar != VAR_REF) { __spf_print(1, "Left part of PARAMETER clause must be a variable in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Left part of PARAMETER clause must be a variable."); __spf_printToLongBuf(messageR, R176); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1058)); retVal = false; } auto assignExp = assign.second->GetOriginal(); auto result = checkParametersExpressionRec(st, attributeStatement, assignExp, messagesForFile); retVal = retVal && result; } return retVal; } static bool checkShadowAcross(SgStatement *st, SgStatement *attributeStatement, const vector, vector>>> &data, vector &messagesForFile) { // SHADOW (VAR(list of shadows)) / ACROSS (VAR(list of shadows)) const int var = st->variant(); bool retVal = true; if (var == FOR_NODE) { for (int i = 0; i < data.size(); ++i) { SgSymbol *arraySymbol = data[i].first.first->GetOriginal(); SgStatement *declStatement = declaratedInStmt(arraySymbol); const vector> &arrayDisc = data[i].second; bool notPrivCond = true; if (arraySymbol->type()->variant() != T_ARRAY) { __spf_print(1, "variable '%s' is not array on line %d\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not array", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R28, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1006)); retVal = false; } notPrivCond = !isPrivateVar(st, arraySymbol) && !isPrivateVar(declStatement, arraySymbol); if (!notPrivCond) { __spf_print(1, "array '%s' on line %d is private\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array '%s' is private", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R33, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1009)); retVal = false; } SgArrayType *arrayType = NULL; if (arraySymbol->type()) arrayType = isSgArrayType(arraySymbol->type()); if (arrayType) { int dim = arrayType->dimension(); if (dim != arrayDisc.size()) { __spf_print(1, "dimention of array '%s' is %d, but you enter %d on line %d\n", arraySymbol->identifier(), arrayType->dimension(), (int)arrayDisc.size(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"dimention of array '%s' is %d, but you enter %d", to_wstring(arraySymbol->identifier()).c_str(), arrayType->dimension(), (int)arrayDisc.size()); __spf_printToLongBuf(messageR, R32, to_wstring(arraySymbol->identifier()).c_str(), arrayType->dimension(), (int)arrayDisc.size()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1008)); retVal = false; } } else { __spf_print(1, "variable '%s' is not array on line %d\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable '%s' is not array", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R29, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1006)); retVal = false; } for (auto &array : arrayDisc) { if (array.first < 0 || array.second < 0) { __spf_print(1, "only positive numbers are supported on line %d\n", attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"only positive numbers are supported"); __spf_printToLongBuf(messageR, R35); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1010)); retVal = false; } } } } else { BAD_POSITION_FULL(ERROR, "before", RR1_1, "", L"", "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } return retVal; } static int hasName(SgExpression *exp, const string &varName) { if (exp) { SgSymbol *symb = exp->symbol(); SgExpression *lhs = exp->lhs(); SgExpression *rhs = exp->rhs(); if (symb) if (string(symb->identifier()) == varName) return 1; return hasName(lhs, varName) + hasName(rhs, varName); } return 0; } static bool isRemoteExpressions(SgExpression *exp, SgExpression *remoteExp, map &collection) { if (exp == remoteExp) return true; bool retVal = true; while (retVal && exp != NULL && remoteExp != NULL) { if (remoteExp->lhs()) if (remoteExp->lhs()->variant() != DDOT) retVal = retVal && isEqExpressions(exp->lhs(), remoteExp->lhs(), collection); exp = exp->rhs(); remoteExp = remoteExp->rhs(); } return retVal; } static bool hasRemoteExpressions(SgExpression *exp, SgExpression *remoteExp, map &collection) { if (exp) { SgExpression *lhs = exp->lhs(); SgExpression *rhs = exp->rhs(); if (exp->variant() == ARRAY_REF && string(exp->symbol()->identifier()) == remoteExp->symbol()->identifier()) if (isRemoteExpressions(exp->lhs(), remoteExp->lhs(), collection)) return true; return hasRemoteExpressions(lhs, remoteExp, collection) || hasRemoteExpressions(rhs, remoteExp, collection); } return false; } static bool checkRemote(SgStatement *st, SgStatement *attributeStatement, const map, Expression*> &remote, vector &messagesForFile) { // REMOTE_ACCESS (EXPR) const int var = st->variant(); bool retVal = true; if (var == FOR_NODE || isSgExecutableStatement(st)) { for (auto &remElem : remote) { bool cond = false; SgStatement *declStatement = declaratedInStmt(remElem.first.first->GetOriginal()); set arraySymbols; vector dummy; fillVars(remElem.second, { ARRAY_REF }, arraySymbols, dummy); for (auto &arraySymbol : arraySymbols) { declStatement = declaratedInStmt(arraySymbol); bool notPrivCond = !isPrivateVar(st, arraySymbol) && !isPrivateVar(declStatement, arraySymbol); if (!notPrivCond) { __spf_print(1, "array '%s' is private on line %d\n", arraySymbol->identifier(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array '%s' is private", to_wstring(arraySymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R34, to_wstring(arraySymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1009)); retVal = false; } } if (var == FOR_NODE) { SgStatement *iterator = st; SgStatement *end = st->lastNodeOfStmt(); map forVars; while (iterator != end) { SgForStmt *forSt = isSgForStmt(iterator); if (forSt) { SgSymbol *forName = forSt->doName(); forVars.insert(make_pair(string(forName->identifier()), 0)); } iterator = iterator->lexNext(); } // CHECK: i AND a * i + b // remElem.second links to b(i,j,k) // remElem.second->lhs() links to i,j,k SgExpression *remoteExp = remElem.second->lhs(); while (remoteExp) { int forVarsCount = 0; for (auto &forVar : forVars) { if (hasName(remoteExp->lhs(), forVar.first)) { ++forVarsCount; ++forVar.second; if (retVal && forVarsCount > 1 || forVar.second > 1) { __spf_print(1, "bad directive expression: too many DO variables on line %d\n", attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: too many DO variables"); __spf_printToLongBuf(messageR, R2); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1001)); retVal = false; } // CHECK TREE: i OR a * i OR a * i + b SgExpression *list = remoteExp->lhs(); bool isRemoteSubTreeCond = false; if (list->variant() == ADD_OP) { if (list->lhs()->variant() == MULT_OP && !hasName(list->rhs(), forVar.first)) { if (hasName(list->lhs(), forVar.first) == 1) isRemoteSubTreeCond = true; } else if (list->rhs()->variant() == MULT_OP && !hasName(list->lhs(), forVar.first)) { if (hasName(list->rhs(), forVar.first) == 1) isRemoteSubTreeCond = true; } else if (hasName(list, forVar.first) == 1) isRemoteSubTreeCond = true; } else if (list->variant() == MULT_OP) { if (!hasName(list->lhs(), forVar.first) && hasName(list->rhs(), forVar.first) == 1 || !hasName(list->rhs(), forVar.first) && hasName(list->lhs(), forVar.first) == 1) isRemoteSubTreeCond = true; } else if (hasName(list, forVar.first) == 1) isRemoteSubTreeCond = true; if (!isRemoteSubTreeCond) { __spf_print(1, "bad directive expression: only a * i + b on line %d\n", attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: only a * i + b"); __spf_printToLongBuf(messageR, R3); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1001)); retVal = false; } } } remoteExp = remoteExp->rhs(); } } st = skipDvmDirs(st); SgStatement *iterator = st; SgStatement *end = (var == FOR_NODE) ? st->lastNodeOfStmt() : st->lexNext(); while (iterator != end) { map collection; for (int i = 0; i < 3; ++i) if (hasRemoteExpressions(iterator->expr(i), remElem.second, collection)) cond = true; iterator = iterator->lexNext(); } if (!cond) { __spf_print(1, "no such expression '%s' on line %d\n", remElem.second->unparse(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"no such expression '%s' on loop", to_wstring(remElem.second->unparse()).c_str()); __spf_printToLongBuf(messageR, R36, to_wstring(remElem.second->unparse()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1011)); retVal = false; } } } else { BAD_POSITION_FULL(ERROR, "before", RR1_1, "", L"", "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } return retVal; } static void findAllRefs(SgExpression *ex, set &names) { if (ex) { if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF) if (ex->symbol()) names.insert(ex->symbol()->identifier()); findAllRefs(ex->lhs(), names); findAllRefs(ex->rhs(), names); } } static bool checkParallelRegions(SgStatement *st, const map *commonBlocks, vector &messagesForFile) { bool retVal = true; bool execNext = isSgExecutableStatement(st->lexNext()); if (execNext || st->lexNext()->variant() == ENTRY_STAT) { if (st->variant() == SPF_PARALLEL_REG_DIR) { SgSymbol *identSymbol = st->symbol(); // declaration checking SgStatement *iterator = st; SgStatement *end = st; while (iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR) iterator = iterator->controlParent(); for (; iterator != end && retVal; iterator = iterator->lexNext()) { if (isSPF_stat(iterator) || isDVM_stat(iterator)) continue; if (!isSgExecutableStatement(iterator)) { if (iterator->variant() == VAR_DECL || iterator->variant() == VAR_DECL_90) { set names; findAllRefs(iterator->expr(0), names); if (names.find(identSymbol->identifier()) != names.end()) { __spf_print(1, "wrong parallel region identifier: variable '%s' was declared on line %d on line %d\n", identSymbol->identifier(), iterator->lineNumber(), st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"wrong parallel region identifier: variable '%s' was declared on line %d", to_wstring(identSymbol->identifier()).c_str(), iterator->lineNumber()); __spf_printToLongBuf(messageR, R63, to_wstring(identSymbol->identifier()).c_str(), iterator->lineNumber()); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1031)); retVal = false; } } } else break; } if (commonBlocks) { // common blocks checking for (auto &commonBlockPair : *commonBlocks) { for (auto &variable : commonBlockPair.second->getVariables()) { if (variable->getName() == identSymbol->identifier()) { __spf_print(1, "wrong parallel region identifier: variable '%s' was declared in common block '%s' on line %d\n", identSymbol->identifier(), commonBlockPair.first.c_str(), st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"wrong parallel region identifier: variable '%s' was declared in common block '%s'", to_wstring(identSymbol->identifier()).c_str(), to_wstring(commonBlockPair.first).c_str()); __spf_printToLongBuf(messageR, R64, to_wstring(identSymbol->identifier()).c_str(), to_wstring(commonBlockPair.first).c_str()); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1032)); retVal = false; } } } } // try to find SPF_END_PARALLEL_REG_DIR iterator = st->lexNext(); bool found = false; for (; iterator && !found; iterator = iterator->lexNext()) { const int var = iterator->variant(); if (var == SPF_PARALLEL_REG_DIR) { // intersection __spf_print(1, "bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s', but got 'SPF PARALLEL_REG_DIR' on line %d\n", identSymbol->identifier(), st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s', but got 'SPF PARALLEL_REG_DIR'", to_wstring(identSymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R4, to_wstring(identSymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; break; } else if (var == SPF_END_PARALLEL_REG_DIR) { found = true; if (iterator->controlParent() != st->controlParent()) { __spf_print(1, "bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s' at the same scope on line %d\n", identSymbol->identifier(), st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s' at the same scope", to_wstring(identSymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R5, to_wstring(identSymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; } break; } } if (!found && retVal) { __spf_print(1, "bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s' on line %d\n", identSymbol->identifier(), st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF END PARALLEL_REG_DIR' for identificator '%s'", to_wstring(identSymbol->identifier()).c_str()); __spf_printToLongBuf(messageR, R6, to_wstring(identSymbol->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; } } else { // type == SPF_END_PARALLEL_REG_DIR // try to find SPF_PARALLEL_REG_DIR SgStatement *iterator = st->lexPrev(); SgStatement *end = st->controlParent(); bool found = false; for (; iterator != end && retVal && !found; iterator = iterator->lexPrev()) { const int var = iterator->variant(); if (var == SPF_END_PARALLEL_REG_DIR) { // intersection __spf_print(1, "bad directive position: expected 'SPF PARALLEL_REG_DIR', but got 'SPF END PARALLEL_REG_DIR' on line %d\n", st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF PARALLEL_REG_DIR', but got 'SPF END PARALLEL_REG_DIR'"); __spf_printToLongBuf(messageR, R7); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; break; } else if (var == SPF_PARALLEL_REG_DIR) { found = true; if (iterator->controlParent() != st->controlParent()) { __spf_print(1, "bad directive position: expected 'SPF PARALLEL_REG_DIR' at the same scope on line %d\n", st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF PARALLEL_REG_DIR' at the same scope"); __spf_printToLongBuf(messageR, R8); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; } break; } } if (!found && retVal) { __spf_print(1, "bad directive position: expected 'SPF PARALLEL_REG_DIR' on line %d\n", st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive position: expected 'SPF PARALLEL_REG_DIR'"); __spf_printToLongBuf(messageR, R9); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1001)); retVal = false; } } } else { BAD_POSITION_FULL(ERROR, "after", RR1_4, "", L"", "all declaration statements", RR1_5, st->lineNumber()); retVal = false; } return retVal; } static inline void addSPFtoAttr(SgStatement *st, const string &currFile, map, set>& usersDirectives) { bool cond = false; SgStatement *iterator = skipDvmDirs(st); vector> attributesToProcess; do { SgStatement *prev = iterator->lexPrev(); const int prevVar = prev->variant(); cond = (isSPF_stat(prev) && prevVar != SPF_END_PARALLEL_REG_DIR); if (cond) { if ((prev->fileName() == currFile) && prevVar != SPF_PARALLEL_REG_DIR) attributesToProcess.push_back(std::make_pair(prev, true)); else attributesToProcess.push_back(std::make_pair(prev, false)); iterator = prev; } } while (cond); //save direct order of SPF from source code std::reverse(attributesToProcess.begin(), attributesToProcess.end()); for (auto& attr : attributesToProcess) { addToattribute(attr.first, st, attr.first->variant()); auto copy = attr.first->copyPtr(); copy->setlineNumber(attr.first->lineNumber()); copy->setLocalLineNumber(attr.first->localLineNumber()); usersDirectives[std::make_pair(st->fileName(), st->lineNumber())].insert(copy); if (attr.second) attr.first->deleteStmt(); } } static bool checkFissionPrivatesExpansion(SgStatement *st, SgStatement *attributeStatement, const string &currFile, vector &messagesForFile, map, set>& usersDirectives, bool checkVars = false) { bool retVal = true; if (attributeStatement) { vector vars; fillFissionPrivatesExpansionFromComment(new Statement(attributeStatement), vars); if (checkVars && !vars.size()) { __spf_print(1, "bad directive expression: expected list of variables on line %d\n", attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: expected list of variables"); __spf_printToLongBuf(messageR, R76); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1043)); retVal = false; } if (vars.size()) { // move next SPF directives to atributes for (auto s = st; s != st->lastNodeOfStmt()->lexNext(); s = s->lexNext()) addSPFtoAttr(s, currFile, usersDirectives); SgForStmt *forSt = (SgForStmt*)st; const int nestedCount = countPerfectLoopNest(forSt); if (vars.size() > nestedCount) { __spf_print(1, "bad directive expression: expected %d nested loops on line %d but got %d on line %d\n", (int)vars.size(), attributeStatement->lineNumber(), nestedCount, st->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: expected %d nested loops on line %d but got %d", (int)vars.size(), attributeStatement->lineNumber(), nestedCount); __spf_printToLongBuf(messageR, R77, (int)vars.size(), attributeStatement->lineNumber(), nestedCount); messagesForFile.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1043)); retVal = false; } } for (int i = 0; retVal && i < vars.size(); ++i) { SgForStmt *forSt = (SgForStmt*)st; if (forSt->doName()->identifier() != vars[i]) { __spf_print(1, "bad directive expression: expected variable '%s' at %d position on line %d\n", forSt->doName()->identifier(), i + 1, attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"bad directive expression: expected variable '%s' at %d position", to_wstring(forSt->doName()->identifier()).c_str(), i + 1); __spf_printToLongBuf(messageR, R78, to_wstring(forSt->doName()->identifier()).c_str(), i + 1); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1043)); retVal = false; } st = st->lexNext(); } } return retVal; } static bool checkShrink(SgStatement *st, SgStatement *attributeStatement, const string &currFile, vector &messagesForFile) { bool retVal = true; vector>> varDims; fillShrinkFromComment(new Statement(attributeStatement), varDims); for (auto &p : varDims) { auto var = p.first->GetOriginal(); auto dims = p.second; // check variable type SgArrayType *arrType = isSgArrayType(var->type()); if (!arrType) { __spf_print(1, "variable in shrink clause must be array in file '%s' on line %d\n", st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"variable in shrink clause must be array in file '%s'", to_wstring(st->fileName()).c_str()); __spf_printToLongBuf(messageR, R154, to_wstring(st->fileName()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1053)); retVal = false; } else { // check private directives set privatesS; set privates; for (int i = 0; i < st->numberOfAttributes(); ++i) { SgAttribute *attr = st->getAttribute(i); SgStatement *attributeStatement = (SgStatement *)(attr->getAttributeData()); fillPrivatesFromComment(new Statement(attributeStatement), privatesS); } for (auto &elem : privatesS) privates.insert(elem->GetOriginal()); auto it = privates.find(var); if (it == privates.end()) { __spf_print(1, "array '%s' in shrink clause must be also declared in private clause in file '%s' on line %d\n", var->identifier(), st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"array '%s' in shrink clause must be also declared in private clause in file '%s'", to_wstring(var->identifier()).c_str(), to_wstring(st->fileName()).c_str()); __spf_printToLongBuf(messageR, R157, to_wstring(var->identifier()).c_str(), to_wstring(st->fileName()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1056)); retVal = false; } // check mask dimensions if (dims.size() != arrType->dimension()) { __spf_print(1, "length of mask for array '%s' must be %d, but you enter only %d dimenions in file '%s' on line %d\n", var->identifier(), arrType->dimension(), dims.size(), st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"length of mask for array '%s' must be %d, but you enter only %d dimenions in file '%s'", to_wstring(var->identifier()).c_str(), arrType->dimension(), dims.size(), to_wstring(st->fileName()).c_str()); __spf_printToLongBuf(messageR, R155, to_wstring(var->identifier()).c_str(), arrType->dimension(), dims.size(), to_wstring(st->fileName()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1054)); retVal = false; } for (auto i = 0; i < dims.size(); ++i) { auto dimVal = dims[i]; if (dimVal != 0 && dimVal != 1) { __spf_print(1, "wrong mask value in %d position for array '%s': it can be only 0 or 1 in file '%s' on line %d\n", i + 1, var->identifier(), st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"wrong mask value in %d position of array '%s': it can be only 0 or 1 in file '%s'", i + 1, to_wstring(var->identifier()).c_str(), to_wstring(st->fileName()).c_str()); __spf_printToLongBuf(messageR, R156, i + 1, to_wstring(var->identifier()).c_str(), to_wstring(st->fileName()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 1055)); retVal = false; } } } } return retVal; } static bool recIsVarUsed(SgStatement *st, SgExpression *exp, const string &varName) { if (exp) { if (exp->symbol() && exp->symbol()->identifier() == varName) return true; return recIsVarUsed(st, exp->lhs(), varName) || recIsVarUsed(st, exp->rhs(), varName); } return false; } static bool isVarUsed(SgStatement *st, const string &varName, bool doNotGetFuncStat = false) { if (st) { auto funcSt = doNotGetFuncStat ? st : getFuncStat(st); checkNull(funcSt, convertFileName(__FILE__).c_str(), __LINE__); for (auto st = funcSt; st != funcSt->lastNodeOfStmt(); st = st->lexNext()) { for (auto i = 0; i < 3; ++i) { bool found = recIsVarUsed(st, st->expr(i), varName); if (found) return true; } } } return false; } static bool isModuleVar(SgStatement *st, SgStatement *attributeStatement, const string &varName) { auto moduleSymbols = moduleRefsByUseInFunction(st); // check renamed vars for (auto &elem : moduleSymbols) for (auto &var : elem.second) if (varName == var->identifier()) return true; // check all used modules in function vector useStats; fillUsedModulesInFunction(st, useStats); for (auto &useSt : useStats) { map visibleVars; fillVisibleInUseVariables(useSt, visibleVars); if (visibleVars.find(varName) != visibleVars.end()) return true; } return false; } static bool checkCheckpointVarsDecl(SgStatement *st, SgStatement *attributeStatement, const set &vars, const string &op, vector &messagesForFile) { bool retVal = true; for (auto &varS : vars) { auto var = varS->GetOriginal(); bool module = isModuleVar(st, attributeStatement, var->identifier()); if (!module) { bool local = isVarUsed(st, var->identifier()); if (!local) { __spf_print(1, "Variable '%s' in %s clause must be declared at the same module in file '%s' on line %d.\n", var->identifier(), op.c_str(), st->fileName(), attributeStatement->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"Variable '%s' in %s clause must be declared at the same module.", to_wstring(var->identifier()).c_str(), to_wstring(op).c_str()); __spf_printToLongBuf(messageR, R168, to_wstring(var->identifier()).c_str(), to_wstring(op).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5004)); retVal = false; } } } return retVal; } static bool checkCheckpoint(SgStatement *st, SgStatement *attributeStatement, const map &clauses, const set &vars, const set &expt, vector &messagesForFile) { bool retVal = true; bool hasInterval = clauses.find(SPF_INTERVAL_OP) == clauses.end(); bool isExecutable = isSgExecutableStatement(st); for (auto &p : clauses) { auto op = p.first; SgExpression *exprList = p.second->GetOriginal(); switch (op) { case SPF_INTERVAL_OP: { int count = 0; while (exprList) { if (exprList->lhs()) ++count; exprList = exprList->rhs(); } if (count != 1) { wstring messageE, messageR; __spf_print(1, "INTERVAL clause can be used only once in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"INTERVAL clause can be used only once."); __spf_printToLongBuf(messageR, R170, L"INTERVAL"); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5006)); retVal = false; } exprList = p.second->lhs(); if (!exprList || exprList->rhs()->variant() != INT_VAL || exprList->lhs()->variant() != SPF_TIME_OP && exprList->lhs()->variant() != SPF_ITER_OP) { wstring messageE, messageR; __spf_print(1, "The first argument must be TIME or ITER and the second must be integer in INTERVAL clause in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"The first argument must be TIME or ITER and the second must be integer in INTERVAL clause."); __spf_printToLongBuf(messageR, R165); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5001)); retVal = false; } if (!isExecutable) { wstring messageE, messageR; __spf_print(1, "CHECKPOINT directive with INTERVAL clause can be only at executable code section in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"CHECKPOINT directive with INTERVAL clause can be only at executable code section."); __spf_printToLongBuf(messageR, R166, L"INTERVAL"); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5002)); retVal = false; } break; } case SPF_FILES_COUNT_OP: { if (!isExecutable) { wstring messageE, messageR; __spf_print(1, "CHECKPOINT directive with FILES clause can be only at executable code section in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"CHECKPOINT directive with FILES clause can be only at executable code section."); __spf_printToLongBuf(messageR, R166, L"CHECKPOINT", L"FILES"); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5002)); retVal = false; } int count = 0; while (exprList) { if (exprList->lhs()) ++count; exprList = exprList->rhs(); } exprList = p.second; if (count != 1) { wstring messageE, messageR; __spf_print(1, "FILES clause can be used only once in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"FILES clause can be used only once."); __spf_printToLongBuf(messageR, R170, L"FILES"); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5006)); retVal = false; } if (exprList && exprList->lhs()->variant() != INT_VAL) { wstring messageE, messageR; __spf_print(1, "CHECKPOINT directive with FILES clause must contain integer value in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"CHECKPOINT directive with FILES clause must contain integer value."); __spf_printToLongBuf(messageR, R167); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5003)); retVal = false; } break; } case SPF_VARLIST_OP: { retVal = retVal && checkCheckpointVarsDecl(st, attributeStatement, vars, string("VARLIST"), messagesForFile); for (auto &varS : vars) { if (expt.find(varS) != expt.end()) { wstring messageE, messageR; __spf_print(1, "Variable '%s' can't be used in FILES and EXCEPT clauses at the same time in file '%s' on line %d.\n", varS->GetOriginal()->identifier(), st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"Variable '%s' can't be used in FILES and EXCEPT clauses at the same time.", to_wstring(varS->GetOriginal()->identifier()).c_str()); __spf_printToLongBuf(messageR, R172, to_wstring(varS->GetOriginal()->identifier()).c_str()); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5007)); retVal = false; } } break; } case SPF_EXCEPT_OP: { retVal = retVal && checkCheckpointVarsDecl(st, attributeStatement, vars, string("EXEPT"), messagesForFile); break; } case SPF_TYPE_OP: { int count = 0; exprList = exprList->rhs(); while (exprList) { if (exprList->lhs() && exprList->lhs()->variant() != ACC_ASYNC_OP && exprList->lhs()->variant() != SPF_FLEXIBLE_OP) { wstring messageE, messageR; __spf_print(1, "Illegal option in TYPE clause in file '%s' on line %d.\n", st->fileName(), attributeStatement->lineNumber()); __spf_printToLongBuf(messageE, L"Illegal option in TYPE clause."); __spf_printToLongBuf(messageR, R169); messagesForFile.push_back(Messages(ERROR, attributeStatement->lineNumber(), messageR, messageE, 5005)); retVal = false; } ++count; exprList = exprList->rhs(); } break; } default: retVal = false; break; } } return retVal; } static int countSPF_OP(SgStatement *st, const int type, const int op) { int count = 0; if (st) { for (auto &data : getAttributes(st, set{ type })) { SgExpression *exprList = data->expr(0); while (exprList) { if (exprList->lhs()->variant() == op) ++count; exprList = exprList->rhs(); } } } return count; } static bool isSPF_OP(SgStatement *st, const int op) { if (st) { SgExpression *exprList = st->expr(0); while (exprList) { if (exprList->lhs() && exprList->lhs()->variant() == op) return true; exprList = exprList->rhs(); } } return false; } static inline bool processStat(SgStatement *st, const string &currFile, const map *commonBlocks, vector &messagesForFile, map, set>& usersDirectives) { bool retVal = true; if (st->variant() == SPF_PARALLEL_REG_DIR || st->variant() == SPF_END_PARALLEL_REG_DIR) { bool result = checkParallelRegions(st, commonBlocks, messagesForFile); retVal = retVal && result; } // ignore SPF statements if (isSPF_stat(st)) return retVal; addSPFtoAttr(st, currFile, usersDirectives); for (int i = 0; i < st->numberOfAttributes(); ++i) { SgAttribute *attr = st->getAttribute(i); SgStatement *attributeStatement = (SgStatement *)(attr->getAttributeData()); int type = st->attributeType(i); int count; if (type == SPF_ANALYSIS_DIR) { // !$SPF ANALYSIS // PRIVATE(VAR) set privates; fillPrivatesFromComment(new Statement(attributeStatement), privates, ACC_PRIVATE_OP); if (privates.size()) { bool result = checkPrivate(st, attributeStatement, privates, messagesForFile); retVal = retVal && result; } // PROCESS_PRIVATE(VAR) privates.clear(); fillPrivatesFromComment(new Statement(attributeStatement), privates, SPF_PROCESS_PRIVATE_OP); if (privates.size()) { bool result = checkProcessPrivate(st, attributeStatement, privates, messagesForFile); retVal = retVal && result; } // REDUCTION(OP(VAR), MIN/MAXLOC(VAR, ARRAY, CONST)) map> reduction; map>> reductionLoc; fillReductionsFromComment(new Statement(attributeStatement), reduction); fillReductionsFromComment(new Statement(attributeStatement), reductionLoc); if (reduction.size()) { bool result = checkReduction(st, attributeStatement, reduction, messagesForFile); bool resultLoc = checkReduction(st, attributeStatement, reductionLoc, messagesForFile); retVal = retVal && result && resultLoc; } // PARAMETER(ident=expr) vector> assigns; fillParameterFromComment(new Statement(attributeStatement), assigns); if (assigns.size()) { bool result = checkParameter(st, attributeStatement, assigns, messagesForFile); retVal = retVal && result; } // COVER if (isSPF_OP(attributeStatement, SPF_COVER_OP) && (count = countSPF_OP(st, SPF_ANALYSIS_DIR, SPF_COVER_OP))) { attributeStatement->setLocalLineNumber(-1); if (count > 1 || st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "once", RR1_7, "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } else { bool result = checkCover(st, attributeStatement, getCoverPropertyFromComment(new Statement(attributeStatement)), messagesForFile); retVal = retVal && result; } } } else if (type == SPF_PARALLEL_DIR) { // !$SPF PARALLEL // SHADOW (VAR(list of shadows)) / ACROSS (VAR(list of shadows)) vector, vector>>> data; fillShadowAcrossFromComment(SHADOW_OP, new Statement(attributeStatement), data); fillShadowAcrossFromComment(ACROSS_OP, new Statement(attributeStatement), data); if (data.size()) { bool result = checkShadowAcross(st, attributeStatement, data, messagesForFile); retVal = retVal && result; } // REMOTE_ACCESS (EXPR) map, Expression*> remote; fillRemoteFromComment(new Statement(attributeStatement), remote, true); if (remote.size()) { bool result = checkRemote(st, attributeStatement, remote, messagesForFile); retVal = retVal && result; } } else if (type == SPF_TRANSFORM_DIR) { // !$SPF TRANSFORM // NOINLINE if (isSPF_NoInline(new Statement(st))) { SgStatement *prev = st->lexPrev(); const int prevVar = prev->variant(); if (prevVar != PROC_HEDR && prevVar != FUNC_HEDR) { BAD_POSITION_FULL(ERROR, "after", RR1_4, "", L"", "function statements", RR1_6, attributeStatement->lineNumber()); retVal = false; } } // FISSION if (isSPF_OP(attributeStatement, SPF_FISSION_OP) && (count = countSPF_OP(st, SPF_TRANSFORM_DIR, SPF_FISSION_OP))) { attributeStatement->setLocalLineNumber(-1); if (count > 1 || st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "once", RR1_7, "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } else { bool result = checkFissionPrivatesExpansion(st, attributeStatement, currFile, messagesForFile, usersDirectives, true); retVal = retVal && result; } } // PRIVATES_EXPANSION if (isSPF_OP(attributeStatement, SPF_EXPAND_OP) && (count = countSPF_OP(st, SPF_TRANSFORM_DIR, SPF_EXPAND_OP))) { attributeStatement->setLocalLineNumber(-1); if (count > 1 || st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "once", RR1_7, "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } else { bool result = checkFissionPrivatesExpansion(st, attributeStatement, currFile, messagesForFile, usersDirectives); retVal = retVal && result; } } // SHRINK if (isSPF_OP(attributeStatement, SPF_SHRINK_OP)) { attributeStatement->setLocalLineNumber(-1); if (st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "", "", "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } else { bool result = checkShrink(st, attributeStatement, currFile, messagesForFile); retVal = retVal && result; } } // UNROLL if (isSPF_OP(attributeStatement, SPF_UNROLL_OP)) { attributeStatement->setLocalLineNumber(-1); if (st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "", "", "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } } // MERGE if (isSPF_OP(attributeStatement, SPF_MERGE_OP)) { attributeStatement->setLocalLineNumber(-1); if (st->variant() != FOR_NODE) { BAD_POSITION_FULL(ERROR, "", "", "before", RR1_1, "DO statement", RR1_3, attributeStatement->lineNumber()); retVal = false; } } } else if (type == SPF_CHECKPOINT_DIR) { map clauses; set vars, expt; fillCheckpointFromComment(new Statement(attributeStatement), clauses, vars, expt); if (clauses.size()) { bool result = checkCheckpoint(st, attributeStatement, clauses, vars, expt, messagesForFile); retVal = retVal && result; } } } return retVal; } static bool checkContainsRegion(SgStatement* st, const string& currFile, const map* commonBlocks, vector& messagesForFile, map, set>& usersDirectives) { bool retVal = true; if (st->variant() != CONTAINS_STMT) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); do { st = st->lexNext(); bool result = processStat(st, currFile, commonBlocks, messagesForFile, usersDirectives); retVal = retVal && result; } while (!isSgProgHedrStmt(st) && st->variant() != CONTROL_END); return retVal; } static bool processModules(vector &modules, const string &currFile, const map *commonBlocks, vector &messagesForFile, const set& allFileNames, map, set>& usersDirectives) { bool retVal = true; for (int i = 0; i < modules.size(); ++i) { SgStatement *modIterator = modules[i]; SgStatement *modEnd = modules[i]->lastNodeOfStmt(); // skip included file const string modFile = modIterator->fileName(); if (modFile != currFile && allFileNames.find(modFile) != allFileNames.end()) continue; do { modIterator = modIterator->lexNext(); if (modIterator->variant() == CONTAINS_STMT) { bool result = checkContainsRegion(modIterator, currFile, commonBlocks, messagesForFile, usersDirectives); retVal = retVal && result; break; } bool result = processStat(modIterator, currFile, commonBlocks, messagesForFile, usersDirectives); retVal = retVal && result; SgStatement *next = modIterator->lexNext(); if (next) if (next->variant() == SPF_END_PARALLEL_REG_DIR) addToattribute(next, modIterator, SPF_END_PARALLEL_REG_DIR); } while (modIterator != modEnd); } return retVal; } bool check_par_reg_dirs(SgFile *file, vector &messagesForFile) { int funcNum = file->numberOfFunctions(); const string currFile = file->filename(); bool noError = true; for (int i = 0; i < funcNum; ++i) { SgStatement *st = file->functions(i); SgStatement *lastNode = st->lastNodeOfStmt(); while (st != lastNode) { if (st == NULL) { __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) break; if (st->variant() == SPF_PARALLEL_REG_DIR || st->variant() == SPF_END_PARALLEL_REG_DIR) { bool result = checkParallelRegions(st, NULL, messagesForFile); noError = noError && result; } st = st->lexNext(); } } return noError; } static void distributeAnalysisWithCover(SgFile* file) { int funcNum = file->numberOfFunctions(); const string currFile = file->filename(); for (int i = 0; i < funcNum; ++i) { SgStatement* st = file->functions(i); SgStatement* lastNode = st->lastNodeOfStmt(); map, int>> spfAnalysis; do { st = st->lexNext(); if (st == NULL) { __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) break; if (st->variant() == FOR_NODE) { pair, int> newData = { set(), 0 }; for (auto& data : getAttributes(st, set{ SPF_ANALYSIS_DIR })) { newData.first.insert(data); int cover = getCoverPropertyFromComment(new Statement(data)); if (cover != 0) newData.second = cover; } if (newData.first.size()) spfAnalysis[st] = newData; } } while (st != lastNode); for (auto& data : spfAnalysis) { SgForStmt* st = isSgForStmt(data.first); checkNull(st, convertFileName(__FILE__).c_str(), __LINE__); int level = st->isPerfectLoopNest(); if (data.second.second < level && data.second.second != 0) level = data.second.second; for (int z = 0; z < level - 1; ++z) { st = isSgForStmt(st->lexNext()); checkNull(st, convertFileName(__FILE__).c_str(), __LINE__); for (auto& dirs : data.second.first) { auto copy = dirs->copyPtr(); copy->setLocalLineNumber(SPF_USER_DIR_COPY); st->addAttribute(copy->variant(), copy, sizeof(SgStatement)); } } } } } bool preprocess_spf_dirs(SgFile *file, const map &commonBlocks, vector &messagesForFile, const set& allFileNames, map, set>& usersDirectives) { int funcNum = file->numberOfFunctions(); const string currFile = file->filename(); bool noError = true; for (int i = 0; i < funcNum; ++i) { SgStatement *st = file->functions(i); SgStatement *lastNode = st->lastNodeOfStmt(); do { st = st->lexNext(); if (st == NULL) { __spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) { bool result = checkContainsRegion(st, currFile, &commonBlocks, messagesForFile, usersDirectives); noError = noError && result; break; } bool result = processStat(st, currFile, &commonBlocks, messagesForFile, usersDirectives); noError = noError && result; SgStatement *next = st->lexNext(); if (next) if (next->variant() == SPF_END_PARALLEL_REG_DIR) addToattribute(next, st, SPF_END_PARALLEL_REG_DIR); } while (st != lastNode); } vector modules; findModulesInFile(file, modules); bool result = processModules(modules, currFile, &commonBlocks, messagesForFile, allFileNames, usersDirectives); noError = noError && result; if (noError) distributeAnalysisWithCover(file); return noError; } static void LinkTree(SgExpression *mainExp, SgExpression *exp) { SgExpression *copyExp = &(exp->copy()); SgExpression *rhs = mainExp->rhs(); while (rhs) { SgExpression *a = rhs; rhs = mainExp->rhs(); mainExp = a; } mainExp->setRhs(copyExp); } static void OptimizeTree(SgExpression *exp) { while (exp) { SgExpression *checkExp = exp->lhs(); SgExpression *currExp = exp->rhs(); SgExpression *prevExp = exp; int var = checkExp->variant(); while (currExp) { SgExpression *lhs = currExp->lhs(); SgExpression *rhs = currExp->rhs(); if (lhs) { if (lhs->variant() == var) { prevExp->setRhs(rhs); LinkTree(checkExp->lhs(), lhs->lhs()); } else prevExp = currExp; currExp = rhs; } } exp = exp->rhs(); } } static SgStatement* UniteAttributes(const vector &sameAtt) { set uniqAttrs; SgStatement *toAddExp = NULL; for (auto &elem : sameAtt) { if (elem->expr(0) == NULL) continue; const string currAtr(elem->unparse()); auto it = uniqAttrs.find(currAtr); if (it == uniqAttrs.end()) uniqAttrs.insert(it, currAtr); else continue; if (toAddExp) { SgExpression *exp = elem->expr(0); LinkTree(toAddExp->expr(0), exp); } else toAddExp = &(elem->copy()); } if (toAddExp) OptimizeTree(toAddExp->expr(0)); //check null of expressions if (toAddExp) { vector list; SgExpression* ex = toAddExp->expr(0); bool deleted = false; while (ex) { if (ex->lhs()->lhs()) list.push_back(ex->lhs()); else deleted = true; ex = ex->rhs(); } if (deleted) toAddExp->setExpression(0, makeExprList(list)); } return toAddExp; } vector filterUserSpf(const vector &toFilter, bool with_omp) { vector ret; for (auto &elem : toFilter) if (elem->localLineNumber() == SPF_USER_DIR || (elem->localLineNumber() == SPF_OMP_DIR && with_omp)) // user and omp ret.push_back(elem); return ret; } //move PARAMETER to operator after a(1:N) = 0 to loop convertation static bool moveSpfParameterForImplicitLoops(SgStatement* st, SgStatement* toAdd) { bool moveNext = false; if (st->lineNumber() < 0 && st->variant() == FOR_NODE) { for (auto ex = toAdd->expr(0); ex; ex = ex->rhs()) if (ex->lhs() && ex->lhs()->variant() == SPF_PARAMETER_OP) moveNext = true; if (moveNext) { int countOp = 0; for (auto t = st->lexNext(); t != st->lastNodeOfStmt(); t = t->lexNext()) countOp++; if (countOp == 1) st->lexNext()->insertStmtBefore(*toAdd, *st->lexNext()->controlParent()); else moveNext = false; } } return moveNext; } static void insertBefore(SgStatement* st, SgStatement* toAdd) { if (toAdd == NULL) return; st->insertStmtBefore(*toAdd, *st->controlParent()); if (st->variant() == FOR_NODE) { auto com = st->comments(); if (com) { st->lexPrev()->addComment(com); st->delComments(); } } } void revertion_spf_dirs(SgFile *file, map, pair> declaredArrays, map>> declaratedArraysSt) { const string fileName(file->filename()); vector units; getModulesAndFunctions(file, units); for (int i = 0; i < units.size(); ++i) { SgStatement *st = units[i]; SgStatement *lastNode = st->lastNodeOfStmt(); for ( ; st != lastNode; st = st->lexNext()) { if (st == NULL) { __spf_print(1, "internal error in analysis, spf directives will not be returned for this file!\n"); break; } if (st->variant() == CONTAINS_STMT) break; if (st->variant() < 0) continue; //analyze attributes SgAttribute *atrib = st->getAttribute(0); SgStatement *toAdd = NULL; if (atrib && st->fileName() == fileName) { //check previosly directives SPF_ANALYSIS vector sameAtt = filterUserSpf(getAttributes(st, set{SPF_ANALYSIS_DIR})); if (sameAtt.size()) { toAdd = UniteAttributes(sameAtt); if (toAdd) if (!moveSpfParameterForImplicitLoops(st, toAdd)) insertBefore(st, toAdd); } //check previosly directives SPF_PARALLEL if (sameAtt.size()) { sameAtt = filterUserSpf(getAttributes(st, set{SPF_PARALLEL_DIR})); for (auto &elem : sameAtt) { if (toAdd) toAdd = UniteAttributes(sameAtt); insertBefore(st, toAdd); } } //remaining directives sameAtt = filterUserSpf(getAttributes(st, set{SPF_CHECKPOINT_DIR, SPF_TRANSFORM_DIR, SPF_NOINLINE_OP, SPF_REGION_NAME})); if (sameAtt.size()) { for (auto &elem : sameAtt) { SgStatement *data = (SgStatement *)atrib->getAttributeData(); SgStatement *toAdd = &(data->copy()); if (toAdd) insertBefore(st, toAdd); } } } } } } void addAcrossToLoops(LoopGraph *topLoop, const map> &acrossToAdd, const map &allLoops, vector &currMessages) { if (acrossToAdd.size() != 0) { SgStatement *acrSpf = new SgStatement(SPF_PARALLEL_DIR, NULL, NULL, NULL, NULL, NULL); SgExpression *exprList = new SgExpression(EXPR_LIST, new SgExpression(ACROSS_OP), NULL, NULL); acrSpf->setExpression(0, *exprList); exprList = exprList->lhs(); SgExpression *newList = new SgExpression(EXPR_LIST); exprList->setLhs(newList); exprList = exprList->lhs(); int k = 0; for (auto it = acrossToAdd.begin(); it != acrossToAdd.end(); ++it, ++k) { SgSymbol *arrayS = it->first; int pos = std::get<2>(it->second); pair ref = std::make_pair(std::get<0>(it->second), std::get<1>(it->second)); SgArrayType *arrType = isSgArrayType(arrayS->type()); if (!arrType) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (arrType->dimension() <= pos) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgArrayRefExp *toAdd = new SgArrayRefExp(*arrayS); for (int z = 0; z < arrType->dimension(); ++z) { if (z == pos) { SgValueExp *tmp = new SgValueExp(ref.first); SgValueExp *tmp1 = new SgValueExp(ref.second); SgExpression *tmp2 = new SgExpression(DDOT, tmp, tmp1, NULL); toAdd->addSubscript(*tmp2); } else { SgValueExp *tmp = new SgValueExp(0); SgValueExp *tmp1 = new SgValueExp(0); SgExpression *tmp2 = new SgExpression(DDOT, tmp, tmp1, NULL); toAdd->addSubscript(*tmp2); } } exprList->setLhs(toAdd); if (consoleMode) printf(" add across dependencies by array '%s' for loop on line %d\n", arrayS->identifier(), topLoop->lineNum); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"add across dependencies by array '%s' to loop", to_wstring(arrayS->identifier()).c_str()); __spf_printToLongBuf(messageR, R108, to_wstring(arrayS->identifier()).c_str()); currMessages.push_back(Messages(NOTE, topLoop->lineNum, messageR, messageE, 3001)); if (k != acrossToAdd.size() - 1) { SgExpression *tmp = new SgExpression(EXPR_LIST); exprList->setRhs(tmp); exprList = exprList->rhs(); } } auto it = allLoops.find(topLoop->lineNum); if (it == allLoops.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); it->second->addAttribute(SPF_PARALLEL_DIR, acrSpf, sizeof(SgStatement)); } } void addPrivatesToLoops(LoopGraph *topLoop, const vector &privatesToAdd, const map &allLoops, vector &currMessages) { if (privatesToAdd.size() != 0) { vector addForCurrLoop; for (int i = 0; i < privatesToAdd.size(); ++i) { const int privLine = privatesToAdd[i]->stmtin->lineNumber(); if (topLoop->lineNum <= privLine && topLoop->lineNumAfterLoop > privLine) addForCurrLoop.push_back(privatesToAdd[i]); } if (addForCurrLoop.size()) { SgStatement *privSpf = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, NULL, NULL, NULL); SgExpression *tmp = new SgExpression(ACC_PRIVATE_OP); SgExpression *exprList = new SgExpression(EXPR_LIST, tmp, NULL, NULL); privSpf->setExpression(0, *exprList); exprList = exprList->lhs(); SgExpression *tmp1 = new SgExpression(EXPR_LIST); exprList->setLhs(tmp1); exprList = exprList->lhs(); auto itLoop = allLoops.find(topLoop->lineNum); if (itLoop == allLoops.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); set added; for (auto &data : getAttributes(itLoop->second, set{ SPF_ANALYSIS_DIR })) fillPrivatesFromComment(new Statement(data), added); int uniq = 0; int k = 0; while (k != addForCurrLoop.size()) { string identifier = addForCurrLoop[k]->varin->symbol()->identifier(); auto itF = added.find(identifier); if (itF == added.end()) itF = added.insert(itF, identifier); else { addForCurrLoop.erase(addForCurrLoop.begin() + k); continue; } k++; uniq++; } for (int k = 0; k < addForCurrLoop.size(); ++k) { string identifier = addForCurrLoop[k]->varin->symbol()->identifier(); exprList->setLhs(addForCurrLoop[k]->varin); if (consoleMode) printf(" add private scalar '%s' for loop on line %d\n", identifier.c_str(), topLoop->lineNum); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"add private scalar '%s' to loop on line %d", to_wstring(identifier).c_str(), topLoop->lineNum); __spf_printToLongBuf(messageR, R109, to_wstring(identifier).c_str(), topLoop->lineNum); currMessages.push_back(Messages(NOTE, addForCurrLoop[k]->stmtin->lineNumber(), messageR, messageE, 3002)); if (k != addForCurrLoop.size() - 1) { SgExpression *tmp = new SgExpression(EXPR_LIST); exprList->setRhs(tmp); exprList = exprList->rhs(); } } if (uniq > 0) itLoop->second->addAttribute(SPF_ANALYSIS_DIR, privSpf, sizeof(SgStatement)); } } } static bool addReductionToList(const char *oper, SgExpression *exprList, SgExpression *varin) { SgExpression *tmp3 = new SgKeywordValExp(oper); SgExpression *tmp4 = new SgExpression(ARRAY_OP, tmp3, varin, NULL); exprList->setLhs(tmp4); return true; } void addReductionsToLoops(LoopGraph *topLoop, const vector &reductionsToAdd, const map &allLoops, vector &currMessages) { if (reductionsToAdd.size() != 0) { vector addForCurrLoop; for (int i = 0; i < reductionsToAdd.size(); ++i) { const int privLine = reductionsToAdd[i]->stmtin->lineNumber(); if (topLoop->lineNum < privLine && topLoop->lineNumAfterLoop > privLine) addForCurrLoop.push_back(reductionsToAdd[i]); } if (addForCurrLoop.size()) { SgStatement *redSpf = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, NULL, NULL, NULL); SgExpression *tmp = new SgExpression(REDUCTION_OP); SgExpression *exprList = new SgExpression(EXPR_LIST, tmp, NULL, NULL); redSpf->setExpression(0, *exprList); exprList = exprList->lhs(); SgExpression *tmp1 = new SgExpression(EXPR_LIST); exprList->setLhs(tmp1); exprList = exprList->lhs(); bool wasAdd = false; for (int k = 0; k < addForCurrLoop.size(); ++k) { if (k != 0 && wasAdd) { SgExpression *tmp = new SgExpression(EXPR_LIST); exprList->setRhs(tmp); exprList = exprList->rhs(); } wasAdd = false; const char *oper = NULL; switch (addForCurrLoop[k]->kinddep) { case SADDREDUCTION: case DADDREDUCTION: case IADDREDUCTION: oper = "sum"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case SMULREDUCTION: case DMULREDUCTION: case IMULREDUCTION: oper = "product"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case SDIVREDUCTION: case DDIVREDUCTION: case IDIVREDUCTION: break; case SMAXREDUCTION: case DMAXREDUCTION: case IMAXREDUCTION: oper = "max"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case SMINREDUCTION: case DMINREDUCTION: case IMINREDUCTION: oper = "min"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case ANDREDUCTION: oper = "and"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case ORREDUCTION: oper = "or"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case EQVREDUCTION: oper = "eqv"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; case NEQVREDUCTION: oper = "neqv"; wasAdd = addReductionToList(oper, exprList, addForCurrLoop[k]->varin); break; default: break; } if (wasAdd) { if (consoleMode) printf(" add reduction scalar '%s' with operation '%s' to loop on line %d\n", addForCurrLoop[k]->varin->symbol()->identifier(), oper, topLoop->lineNum); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"add reduction scalar '%s' with operation '%s' to loop on line %d", to_wstring(addForCurrLoop[k]->varin->symbol()->identifier()).c_str(), to_wstring(oper).c_str(), topLoop->lineNum); __spf_printToLongBuf(messageR, R110, to_wstring(addForCurrLoop[k]->varin->symbol()->identifier()).c_str(), to_wstring(oper).c_str(), topLoop->lineNum); currMessages.push_back(Messages(NOTE, addForCurrLoop[k]->stmtin->lineNumber(), messageR, messageE, 3003)); } else { if (consoleMode) printf(" unknown type of reduction scalar '%s' on line %d\n", addForCurrLoop[k]->varin->symbol()->identifier(), addForCurrLoop[k]->stmtin->lineNumber()); wstring messageE, messageR; __spf_printToLongBuf(messageE, L"unknown type of reduction scalar '%s'", to_wstring(addForCurrLoop[k]->varin->symbol()->identifier()).c_str()); __spf_printToLongBuf(messageR, R111, to_wstring(addForCurrLoop[k]->varin->symbol()->identifier()).c_str()); currMessages.push_back(Messages(WARR, addForCurrLoop[k]->stmtin->lineNumber(), messageR, messageE, 3004)); topLoop->hasUnknownScalarDep = true; topLoop->linesOfScalarDep.push_back(addForCurrLoop[k]->stmtin->lineNumber()); } } auto it = allLoops.find(topLoop->lineNum); if (it == allLoops.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); it->second->addAttribute(SPF_ANALYSIS_DIR, redSpf, sizeof(SgStatement)); } } }