Files
SAPFOR/Sapfor/_src/DirectiveProcessing/spf_directive_preproc.cpp
2025-03-12 12:37:19 +03:00

2668 lines
106 KiB
C++

#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <assert.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#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<int>& types, set<string>& identifierList, vector<SgExpression*>& 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<int> &types, set<SgSymbol*> &identifierList, vector<SgExpression*> &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<SgStatement*, SgStatement*>(st, set<int>{ SPF_ANALYSIS_DIR }))
{
set<string> 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<string> &varDef, set<string> &varUse)
{
for ( ;iterator != end; iterator = iterator->lexNext())
{
vector<SgExpression*> 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<SgExpression*> 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<Messages>& 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<Symbol*>& privates,
vector<Messages>& 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<string> 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<Symbol*> &privates,
vector<Messages> &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<string> varDef, varUse;
set<string> 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<SgExpression*> 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<string, set<Symbol*>> &reduction,
vector<Messages> &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<string> varDef;
set<string> 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<string, set<tuple<Symbol*, Symbol*, int>>> &reduction,
vector<Messages> &messagesForFile)
{
// REDUCTION(MIN/MAXLOC(VAR, ARRAY, CONST))
bool retVal = true;
for (auto &redElem : reduction)
{
set<Symbol*> vars;
set<Symbol*> arrs;
set<string> varsS;
set<string> 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<SgExpression*> 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<string, set<Symbol*>> reductionVar;
map<string, set<Symbol*>> 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<Messages> &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<SgStatement*> useStats;
fillUsedModulesInFunction(st, useStats);
for (auto& useSt : useStats)
{
map<string, SgSymbol*> 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<pair<Expression*, Expression*>> &assigns, vector<Messages> &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<pair<pair<Symbol*, string>, vector<pair<int, int>>>> &data,
vector<Messages> &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<pair<int, int>> &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<SgExpression*, string> &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<SgExpression*, string> &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<pair<Symbol*, string>, Expression*> &remote,
vector<Messages> &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<SgSymbol*> arraySymbols;
vector<SgExpression*> 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<string, int> 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<SgExpression*, string> 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<string> &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<string, CommonBlock*> *commonBlocks,
vector<Messages> &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<string> 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<pair<string, int>, set<SgStatement*>>& usersDirectives)
{
bool cond = false;
SgStatement *iterator = skipDvmDirs(st);
vector<pair<SgStatement*, bool>> 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<Messages> &messagesForFile,
map<pair<string, int>, set<SgStatement*>>& usersDirectives,
bool checkVars = false)
{
bool retVal = true;
if (attributeStatement)
{
vector<string> 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<Messages> &messagesForFile)
{
bool retVal = true;
vector<pair<Symbol *, vector<int>>> 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<Symbol*> privatesS;
set<SgSymbol*> 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<SgStatement*> useStats;
fillUsedModulesInFunction(st, useStats);
for (auto &useSt : useStats)
{
map<string, SgSymbol*> visibleVars;
fillVisibleInUseVariables(useSt, visibleVars);
if (visibleVars.find(varName) != visibleVars.end())
return true;
}
return false;
}
static bool checkCheckpointVarsDecl(SgStatement *st,
SgStatement *attributeStatement,
const set<Symbol*> &vars,
const string &op,
vector<Messages> &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<int, Expression*> &clauses,
const set<Symbol*> &vars,
const set<Symbol*> &expt,
vector<Messages> &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<SgStatement*, SgStatement*>(st, set<int>{ 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<string, CommonBlock*> *commonBlocks,
vector<Messages> &messagesForFile,
map<pair<string, int>, set<SgStatement*>>& 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<Symbol*> 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<string, set<Symbol*>> reduction;
map<string, set<tuple<Symbol*, Symbol*, int>>> 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<pair<Expression*, Expression*>> 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<pair<pair<Symbol*, string>, vector<pair<int, int>>>> 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<pair<Symbol*, string>, 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<int, Expression*> clauses;
set<Symbol*> 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<string, CommonBlock*>* commonBlocks, vector<Messages>& messagesForFile,
map<pair<string, int>, set<SgStatement*>>& 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<SgStatement*> &modules, const string &currFile, const map<string, CommonBlock*> *commonBlocks,
vector<Messages> &messagesForFile, const set<string>& allFileNames,
map<pair<string, int>, set<SgStatement*>>& 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<Messages> &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<SgStatement*, pair<set<SgStatement*>, 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<set<SgStatement*>, int> newData = { set<SgStatement*>(), 0 };
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ 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<string, CommonBlock*> &commonBlocks, vector<Messages> &messagesForFile, const set<string>& allFileNames,
map<pair<string, int>, set<SgStatement*>>& 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<SgStatement*> 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<SgStatement*> &sameAtt)
{
set<string> 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<SgExpression*> 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<SgStatement*> filterUserSpf(const vector<SgStatement*> &toFilter, bool with_omp)
{
vector<SgStatement*> 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<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
map<SgStatement*, set<tuple<int, string, string>>> declaratedArraysSt)
{
const string fileName(file->filename());
vector<SgStatement*> 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<SgStatement*> sameAtt = filterUserSpf(getAttributes<SgStatement*, SgStatement*>(st, set<int>{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<SgStatement*, SgStatement*>(st, set<int>{SPF_PARALLEL_DIR}));
for (auto &elem : sameAtt)
{
if (toAdd)
toAdd = UniteAttributes(sameAtt);
insertBefore(st, toAdd);
}
}
//remaining directives
sameAtt = filterUserSpf(getAttributes<SgStatement*, SgStatement*>(st, set<int>{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<SgSymbol*, tuple<int, int, int>> &acrossToAdd,
const map<int, SgForStmt*> &allLoops,
vector<Messages> &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<int, int> 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<const depNode*> &privatesToAdd,
const map<int, SgForStmt*> &allLoops,
vector<Messages> &currMessages)
{
if (privatesToAdd.size() != 0)
{
vector<const depNode*> 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<string> added;
for (auto &data : getAttributes<SgStatement*, SgStatement*>(itLoop->second, set<int>{ 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<const depNode*> &reductionsToAdd,
const map<int, SgForStmt*> &allLoops,
vector<Messages> &currMessages)
{
if (reductionsToAdd.size() != 0)
{
vector<const depNode*> 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));
}
}
}