2668 lines
106 KiB
C++
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));
|
|
}
|
|
}
|
|
} |