Files
SAPFOR/Sapfor/_src/Inliner/inliner.cpp

2574 lines
96 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "../Utils/leak_detector.h"
#include <stdlib.h>
#include <stdio.h>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include "dvm.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
#include "../GraphCall/graph_calls_func.h"
#include "inliner.h"
#include "../VisualizerCalls/SendMessage.h"
#include "../ExpressionTransform/expr_transform.h"
using std::set;
using std::map;
using std::vector;
using std::pair;
using std::make_pair;
using std::string;
using std::wstring;
using std::to_string;
2023-11-26 18:57:05 +03:00
using std::get;
using std::tuple;
2023-09-14 19:43:13 +03:00
#define DEB 0
extern map<string, vector<SgStatement*>> hiddenData;
static map<SgSymbol*, SgSymbol*> linkToOrig;
static map<pair<string, int>, map<string, SgSymbol*>> createdByFunc; // key == <funcName, fileID>
static map<string, int> createdVarCounterByName;
static map<pair<string, int>, map<string, pair<SgSymbol*, string>>> replacedConstRef; // key == <funcName, fileID>
static map<pair<string, int>, set<SgValueExp*>> dataDeclsByFunc; // key == <funcName, fileID>
static map<pair<string, int>, map<string, SgExpression*>> dataDeclsByFuncS; // key == <funcName, fileID>
struct PointCall
{
private:
bool findChainCall(FuncInfo* call, int lvl, vector<string>& str, const string& toFind) const
{
bool found = false;
if (lvl == 0)
{
for (auto& elem : call->callsFromV)
{
if (elem->funcName == toFind)
{
str.push_back(elem->funcName);
found = true;
break;
}
}
}
else
{
for (auto& elem : call->callsFromV)
{
str.push_back(elem->funcName);
found = findChainCall(elem, lvl - 1, str, toFind);
if (found)
break;
else
str.pop_back();
}
}
return found;
}
public:
pair<string, int> mainPoint;
FuncInfo *func;
string currCall;
int currLvl;
string getChainCall() const
{
string str = func->funcName;
if (currLvl)
{
vector<string> chain;
findChainCall(func, currLvl - 1, chain, currCall);
if (chain.size() != currLvl)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int z = 0; z < chain.size(); ++z)
str += "->" + chain[z];
}
return str;
}
};
static void checkSymbols(const int currFileId, const set<SgSymbol*>& symbs)
{
for (auto& symb : symbs)
{
if (symb->getFileId() != currFileId)
{
2023-11-28 12:58:22 +03:00
__spf_print(1, "check failed - given %d, correct %d\n", symb->getFileId(), currFileId);
2023-09-14 19:43:13 +03:00
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
}
static map<string, SgExpression*> createMapOfArgs(SgStatement* tempHedr, SgExpression* actualArgs)
{
2023-11-28 12:58:22 +03:00
__spf_print(DEB, "------create map of vars------\n");
SgProgHedrStmt* hedr = isSgProgHedrStmt(tempHedr);
checkNull(hedr, convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
2023-11-28 12:58:22 +03:00
int numPars = hedr->numberOfParameters();
map<string, SgExpression*> vars;
2023-09-14 19:43:13 +03:00
int i = 0;
while (actualArgs)
{
2023-11-28 12:58:22 +03:00
if (i >= numPars)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2023-09-14 19:43:13 +03:00
auto actualArg = actualArgs->lhs();
2023-11-28 12:58:22 +03:00
auto formalArg = hedr->parameter(i++);
2023-09-14 19:43:13 +03:00
auto it = vars.find(formalArg->identifier());
if (it == vars.end())
vars.insert(it, make_pair(formalArg->identifier(), actualArg));
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
actualArgs = actualArgs->rhs();
}
return vars;
}
2024-01-23 13:04:46 +03:00
static bool isAllocated(SgSymbol* s)
{
return (s->attributes() & ALLOCATABLE_BIT) || (s->attributes() & POINTER_BIT);
}
2023-09-14 19:43:13 +03:00
static inline SgSymbol* createSymbAndDecl(const string& funcName, const string& varName, SgSymbol* newS, set<SgSymbol*>& newSymbols, SgType* type = NULL)
{
SgSymbol* original = newS;
if (newS)
newS = &newS->copy();
int* count;
if (createdVarCounterByName.find(varName) == createdVarCounterByName.end())
{
createdVarCounterByName[varName] = 0;
count = &createdVarCounterByName[varName];
}
else
count = &createdVarCounterByName[varName];
const string base = varName + "_";
int nextCount = checkSymbNameAndCorrect(base, count[0]);
const string newName = base + to_string(nextCount);
const pair<string, int> key = make_pair(funcName, current_file_id);
if (newS)
{
if (isSgConstantSymb(newS))
{
if (funcName != "null" && createdByFunc[key].find(varName) == createdByFunc[key].end() ||
funcName == "null")
{
auto it = replacedConstRef[key].find(newS->identifier());
if (it != replacedConstRef[key].end() && it->second.first->identifier() != it->second.second)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (it == replacedConstRef[key].end())
{
//check replaces
SgSymbol* wasDone = NULL;
for (auto& elem : replacedConstRef[key])
if (elem.second.second == varName)
wasDone = elem.second.first;
if (wasDone == NULL)
{
replacedConstRef[key][newS->identifier()] = make_pair(newS, newName.c_str());
newS->changeName(newName.c_str());
}
else
newS = wasDone;
}
}
else if (funcName != "null" && createdByFunc[key].find(varName) != createdByFunc[key].end())
{
; //skip
}
else
newS->changeName(newName.c_str());
}
else
newS->changeName(newName.c_str());
}
else
newS = findSymbolOrCreate(current_file, newName, type);
if (newS->variant() == PROCEDURE_NAME)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (funcName != "null")
{
auto itS = createdByFunc[key].find(varName);
if (itS == createdByFunc[key].end())
{
createdByFunc[key][varName] = newS;
count[0] = nextCount;
2024-01-23 13:04:46 +03:00
if (original && isAllocated(original))
2023-09-14 19:43:13 +03:00
linkToOrig[newS] = original;
}
else
newS = itS->second;
}
//printf("newS %s = %d\n", newS->identifier(), newS->id());
newSymbols.insert(newS);
checkSymbols(current_file_id, newSymbols);
return newS;
}
2023-11-05 18:20:31 +03:00
static SgStatement* findDuplicateInHidden(SgStatement* data)
{
SgStatement* clone = NULL;
auto itF = hiddenData.find(current_file->filename());
if (itF == hiddenData.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto& func : itF->second)
{
if (func->fileName() != string(data->fileName()))
continue;
SgStatement* st = func->lexNext();
SgStatement* last = func->lastNodeOfStmt();
while (st != last)
{
if (data->lineNumber() == st->lineNumber() && data->variant() == st->variant())
{
clone = st;
break;
}
st = st->lexNext();
}
if (clone)
break;
}
checkNull(clone, convertFileName(__FILE__).c_str(), __LINE__);
return clone;
}
2023-09-14 19:43:13 +03:00
static SgValueExp* oneExpr = NULL;
static SgValueExp* zeroExpr = NULL;
static vector<SgExpression*> getLowBounds(SgSymbol* arrayS)
{
if (oneExpr == NULL)
oneExpr = new SgValueExp(1);
SgExpression* list = NULL;
2024-01-23 13:04:46 +03:00
if (isAllocated(arrayS))
2023-09-14 19:43:13 +03:00
{
SgSymbol* copyFrom = NULL;
if (linkToOrig.find(arrayS) == linkToOrig.end())
copyFrom = arrayS;
else
copyFrom = linkToOrig[arrayS];
SgStatement* decl = declaratedInStmt(copyFrom);
checkNull(decl, convertFileName(__FILE__).c_str(), __LINE__);
int consistInAllocates = 0;
const string origName = OriginalSymbol(copyFrom)->identifier();
2024-02-25 11:16:56 +03:00
auto allocData = getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT });
if (allocData.size() == 0) // try to find statements in original file
{
string declFile(decl->fileName());
int line = decl->lineNumber();
string file_name = current_file->filename();
if (current_file->filename() != declFile)
{
auto trueDecl = SgStatement::getStatementByFileAndLine(declFile, line);
if (trueDecl)
{
auto trueData = getAttributes<SgStatement*, SgStatement*>(trueDecl, set<int>{ ALLOCATE_STMT });
if (trueData.size())
allocData = trueData;
}
}
SgFile::switchToFile(file_name);
}
for (auto data : allocData)
2023-09-14 19:43:13 +03:00
{
if (data->variant() != ALLOCATE_STMT)
continue;
2023-11-05 18:20:31 +03:00
if (data->getFileId() != current_file_id)
data = findDuplicateInHidden(data);
2023-09-14 19:43:13 +03:00
SgExpression* iter = data->expr(0);
while (iter)
{
SgArrayRefExp* arrayRef = isSgArrayRefExp(iter->lhs());
if (arrayRef != NULL)
{
SgSymbol* origS = OriginalSymbol(arrayRef->symbol());
if (origS->identifier() == origName)
{
consistInAllocates++;
list = iter->lhs()->lhs();
}
}
iter = iter->rhs();
}
}
if (consistInAllocates != 1)
list = NULL;
2024-02-11 21:09:44 +03:00
if (list == NULL)
2024-02-25 11:16:56 +03:00
__spf_print(1, "find for %s, consistInAllocates = %d\n", arrayS->identifier(), consistInAllocates);
2023-09-14 19:43:13 +03:00
checkNull(list, convertFileName(__FILE__).c_str(), __LINE__);
}
else
{
auto type = isSgArrayType(arrayS->type());
list = type->getDimList();
}
vector<SgExpression*> bounds;
while (list)
{
SgExpression* elem = list->lhs();
if (elem->variant() == DDOT)
bounds.push_back(elem->lhs());
else
bounds.push_back(oneExpr);
list = list->rhs();
}
return bounds;
}
static vector<SgExpression*> getBoundsExpression(SgSymbol* arrayS)
{
2024-01-23 13:04:46 +03:00
if (isAllocated(arrayS))
2023-09-14 19:43:13 +03:00
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto type = isSgArrayType(arrayS->type());
auto list = type->getDimList();
vector<SgExpression*> bounds;
while (list)
{
SgExpression* elem = list->lhs();
if (elem->variant() == DDOT)
bounds.push_back(&(elem->rhs()->copy() - elem->lhs()->copy() + *new SgValueExp(1)));
else
bounds.push_back(elem->copyPtr());
list = list->rhs();
}
return bounds;
}
static SgArrayRefExp* addressPass(SgArrayRefExp* result, SgArrayRefExp* arrayExpOld, SgArrayRefExp* arrayExpNew,
const vector<SgExpression*>& boundsOld, const vector<SgExpression*>& boundsNew,
map<SgExpression*, string>& collection)
{
//TODO: check dims position
for (int z = 0; z < boundsOld.size(); ++z)
{
checkNull(boundsOld[z], convertFileName(__FILE__).c_str(), __LINE__);
checkNull(boundsNew[z], convertFileName(__FILE__).c_str(), __LINE__);
2024-02-11 21:09:44 +03:00
SgExpression* shift = NULL;
SgExpression& baseShift = (boundsNew[z]->copy() - boundsOld[z]->copy());
if (arrayExpNew->subscript(z) &&
!isEqExpressions(arrayExpNew->subscript(z), boundsNew[z], collection))
{
shift = &(arrayExpNew->subscript(z)->copy() - boundsNew[z]->copy());
}
SgExpression& oldSub = arrayExpOld->subscript(z)->copy();
2023-09-14 19:43:13 +03:00
if (isEqExpressions(boundsOld[z], boundsNew[z], collection))
2024-02-11 21:09:44 +03:00
result->addSubscript(shift ? (oldSub + *shift) : oldSub);
2023-09-14 19:43:13 +03:00
else
2024-02-11 21:09:44 +03:00
result->addSubscript(shift ? (oldSub + baseShift + *shift) : (oldSub + baseShift));
2023-09-14 19:43:13 +03:00
}
return result;
}
static SgArrayRefExp* linearize(SgArrayRefExp* result, SgArrayRefExp* arrayExpOld, SgExpression* oldExp,
map<string, vector<pair<SgSymbol*, SgExpression*>>>& argVarsLinearForm,
const vector<SgExpression*>& boundsOld, const vector<SgExpression*>& boundsNew,
map<SgExpression*, string>& collection)
{
const string arrayName = oldExp->symbol()->identifier();
const int numOldSubs = arrayExpOld->numberOfSubscripts();
auto itL = argVarsLinearForm.find(arrayName);
if (itL == argVarsLinearForm.end())
{
vector<pair<SgSymbol*, SgExpression*>> newVars;
int boundsN = 0;
auto initDeclareBounds = getBoundsExpression(oldExp->symbol());
for (int z = 0; z < boundsOld.size() - 1; ++z)
{
pair<SgSymbol*, SgExpression*> forDim;
string dimName = "s_";
int nextBoound = checkSymbNameAndCorrect(dimName, boundsN);
dimName += to_string(nextBoound);
forDim.first = new SgSymbol(VARIABLE_NAME, dimName.c_str());
forDim.second = initDeclareBounds[z];
newVars.push_back(forDim);
}
itL = argVarsLinearForm.insert(itL, make_pair(arrayName, newVars));
}
SgExpression* linearForm = NULL;
if (numOldSubs != 0)
{
for (int z = 0; z < boundsOld.size(); ++z)
{
SgExpression* nextArg = &(arrayExpOld->subscript(z)->copy() - boundsOld[z]->copy());
for (int p = 0; p < z; ++p)
nextArg = &(*nextArg * *new SgVarRefExp(itL->second[p].first));
if (linearForm)
linearForm = &(*linearForm + *nextArg);
else
linearForm = nextArg;
}
int numS = result->numberOfSubscripts();
if (!isEqExpressions(zeroExpr, boundsNew[0], collection) && numS == 0)
linearForm = &(*linearForm + boundsNew[0]->copy());
if (numS == 0)
result->addSubscript(*linearForm);
else if (numS == 1)
result->replaceSubscripts(*result->subscript(0) + *linearForm);
else // TODO
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return result;
}
static SgExpression* doReplace(SgExpression* oldExp, SgExpression* newExp, map<SgExpression*, string>& collection,
map<string, vector<pair<SgSymbol*, SgExpression*>>>& argVarsLinearForm,
map<string, vector<Messages>>& messages,
const PointCall& point)
{
if (oneExpr == NULL)
oneExpr = new SgValueExp(1);
if (zeroExpr == NULL)
zeroExpr = new SgValueExp(0);
SgExpression* retVal = NULL;
if (oldExp)
{
if (oldExp->variant() == ARRAY_REF && oldExp->symbol() && oldExp->symbol()->type()->variant() == T_ARRAY)
{
if (newExp->variant() != ARRAY_REF)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgArrayRefExp* arrayExpOld = isSgArrayRefExp(oldExp);
SgArrayRefExp* arrayExpNew = isSgArrayRefExp(newExp);
2024-02-11 21:09:44 +03:00
/*arrayExpOld->unparsestdout();
arrayExpNew->unparsestdout();
printf("\n");*/
2023-09-14 19:43:13 +03:00
auto boundsOld = getLowBounds(oldExp->symbol());
auto boundsNew = getLowBounds(newExp->symbol());
2024-02-11 21:09:44 +03:00
/*for (auto& elem : boundsOld)
elem->unparsestdout();
printf("--\n");
for (auto& elem : boundsNew)
elem->unparsestdout();
printf("--\n");*/
2023-09-14 19:43:13 +03:00
const int numOldSubs = arrayExpOld->numberOfSubscripts();
const int numNewSubs = arrayExpNew->numberOfSubscripts();
if (numNewSubs == 0)
{
SgArrayRefExp* result = (SgArrayRefExp*)arrayExpNew->copyPtr();
if (boundsOld.size() != boundsNew.size() && boundsNew.size() != 1 && boundsOld.size() != 1)
{
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Can not do replace argument of call '%s': sizes mismatch of array reference '%s'",
to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
__spf_printToLongBuf(bufR, R180, to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
getObjectForFileFromMap(point.mainPoint.first.c_str(), messages).push_back(Messages(ERROR, point.mainPoint.second, bufR, bufE, 2014));
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
if (boundsNew.size() == 1 && boundsOld.size() > 1)
result = linearize(result, arrayExpOld, oldExp, argVarsLinearForm, boundsOld, boundsNew, collection);
else if (boundsNew.size() > 1 && boundsOld.size() == 1)
{
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Can not do replace argument of call '%s': sizes mismatch of array reference '%s'",
to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
__spf_printToLongBuf(bufR, R180, to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
getObjectForFileFromMap(point.mainPoint.first.c_str(), messages).push_back(Messages(ERROR, point.mainPoint.second, bufR, bufE, 2014));
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else if (numOldSubs != 0)
result = addressPass(result, arrayExpOld, arrayExpNew, boundsOld, boundsNew, collection);
retVal = result;
}
else if (numNewSubs >= numOldSubs && numOldSubs != 0)
{
SgArrayRefExp* result = new SgArrayRefExp(*arrayExpNew->symbol());
if (boundsOld.size() > boundsNew.size())
{
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Can not do replace argument of call '%s': sizes mismatch of array reference '%s'",
to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
__spf_printToLongBuf(bufR, R180, to_wstring(point.getChainCall()).c_str(), to_wstring(oldExp->symbol()->identifier()).c_str());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
result = addressPass(result, arrayExpOld, arrayExpNew, boundsOld, boundsNew, collection);
for (int z = 0; z < boundsNew.size() - boundsOld.size(); ++z)
result->addSubscript(arrayExpNew->subscript(boundsOld.size() + z)->copy());
retVal = result;
}
else
{
if (boundsNew.size() == 1 && boundsOld.size() > 1)
{
SgArrayRefExp* result = (SgArrayRefExp*)arrayExpNew->copyPtr();
retVal = linearize(result, arrayExpOld, oldExp, argVarsLinearForm, boundsOld, boundsNew, collection);
}
else
{
retVal = newExp->copyPtr();
retVal->setLhs(oldExp->lhs());
retVal->setRhs(oldExp->rhs());
}
}
}
else
retVal = newExp->copyPtr();
}
if (retVal == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return retVal;
}
//return 0 - local, 1 - common, 2 - module
static int isGlobal(SgStatement* st, SgSymbol* toCheckS, vector<SgSymbol*>* allInCommon = NULL, string* globalName = NULL)
{
auto scope = toCheckS->scope();
bool isFunctionS = (toCheckS->variant() == FUNCTION_NAME);
if (toCheckS != OriginalSymbol(toCheckS) || (scope && scope->variant() == MODULE_STMT && !isFunctionS))
{
//TODO for module
//globalName =
return 2;
}
const string toCheck = toCheckS->identifier();
SgStatement* func = getFuncStat(st);
map<string, vector<SgExpression*>> commonBlocksRef;
getCommonBlocksRef(commonBlocksRef, func, func ? func->lastNodeOfStmt() : NULL);
int isCommon = 0;
for (auto& commonBlockRef : commonBlocksRef)
{
for (auto& commExp : commonBlockRef.second)
{
for (auto exp = commExp->lhs(); exp; exp = exp->rhs())
{
SgSymbol* varSymb = exp->lhs()->symbol();
string varName = varSymb->identifier();
if (toCheck == varName)
{
if (globalName)
globalName[0] = commonBlockRef.first;
isCommon = 1;
break;
}
}
if (isCommon == 1)
break;
}
if (isCommon == 1 && allInCommon)
for (auto& commExp : commonBlockRef.second)
for (auto exp = commExp->lhs(); exp; exp = exp->rhs())
allInCommon[0].push_back(exp->lhs()->symbol());
if (isCommon == 1)
break;
}
return isCommon;
}
inline static void findAllConstRef(SgExpression* ex, set<SgSymbol*>& result)
{
if (ex)
{
if (ex->variant() == CONST_REF)
{
result.insert(ex->symbol());
auto constS = isSgConstantSymb(ex->symbol());
if (!constS)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto val = constS->constantValue();
if (!val)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
findAllConstRef(val, result);
}
findAllConstRef(ex->lhs(), result);
findAllConstRef(ex->rhs(), result);
}
}
//globalType: 0 - local, 1 - common, 2 - module
static void detectTypeOfSymbol(const string& funcName, SgSymbol* s, int globalType, set<SgSymbol*>& newSymbols,
const vector<SgSymbol*>& allInCommon, const string& globalName)
{
if (newSymbols.find(s) == newSymbols.end())
{
char* newAttr = new char[globalName.size() + 1];
strcpy(newAttr, globalName.c_str());
if (globalType == 1)
{
if (allInCommon.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const pair<string, int> key = make_pair(funcName, current_file_id);
int pos = 0;
for (auto& commS : allInCommon)
{
auto attrsC = getAttributes<SgSymbol*, char*>(commS, set<int> { COMM_STAT });
auto attrsPos = getAttributes<SgSymbol*, int*>(commS, set<int> { COMM_LIST });
if (attrsC.size() == 0 && attrsPos.size() == 0 ||
attrsC.size() && attrsPos.size() && (attrsC[0] != string(newAttr) || *attrsPos[0] != pos))
{
commS->addAttribute(COMM_STAT, newAttr, sizeof(char*));
int* posS = new int[1];
posS[0] = pos;
commS->addAttribute(COMM_LIST, posS, sizeof(int*));
}
if (isSgArrayType(commS->type()))
{
set<SgSymbol*> constInDecl;
auto arrT = isSgArrayType(commS->type());
findAllConstRef(arrT->getDimList(), constInDecl);
for (auto& elem : constInDecl)
{
auto itS = replacedConstRef[key].find(elem->identifier());
if (itS == replacedConstRef[key].end())
{
replacedConstRef[key][elem->identifier()] = make_pair(elem, elem->identifier());
newSymbols.insert(elem);
checkSymbols(current_file_id, newSymbols);
}
}
}
newSymbols.insert(commS);
checkSymbols(current_file_id, newSymbols);
if (funcName != "null" && commS->attributes() & DATA_BIT)
{
auto itS = createdByFunc[key].find(commS->identifier());
if (itS == createdByFunc[key].end())
createdByFunc[key][commS->identifier()] = commS;
}
++pos;
}
}
else if (globalType == 2)
s->addAttribute(MODULE_STMT, newAttr, sizeof(char*));
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (globalType != 2)
newSymbols.insert(s);
checkSymbols(current_file_id, newSymbols);
}
}
static void replaceSymbInExp(SgStatement* st, SgExpression* exp, SgExpression* par, const int expIdx, const bool isLeft,
const map<string, SgExpression*>& argVars, map<string, SgSymbol*>& locVars, set<SgSymbol*>& newSymbols,
const string& funcName, const string& resultName, SgSymbol*& newHedrSymb, map<SgExpression*, string>& collection,
map<string, vector<pair<SgSymbol*, SgExpression*>>>& argVarsLinearForm,
map<string, vector<Messages>>& messages, const PointCall& point)
{
if (exp)
{
replaceSymbInExp(st, exp->lhs(), exp, expIdx, true, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, argVarsLinearForm, messages, point);
replaceSymbInExp(st, exp->rhs(), exp, expIdx, false, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, argVarsLinearForm, messages, point);
const int var = exp->variant();
if (var == FUNC_CALL && exp->symbol())
if (!isIntrinsicFunctionName(exp->symbol()->identifier()) || exp->symbol()->identifier() == string("dvtime"))
newSymbols.insert(exp->symbol());
if ((var == VAR_REF || var == ARRAY_REF || var == CONST_REF || var == IOACCESS) && exp->symbol())
{
const string varName = exp->symbol()->identifier();
auto it = argVars.find(varName);
if (it != argVars.end())
{
SgExpression* copy = NULL;
if (!par)
{
copy = doReplace(st->expr(expIdx), it->second, collection, argVarsLinearForm, messages, point);
st->setExpression(expIdx, copy);
}
else
{
copy = doReplace((isLeft ? par->lhs() : par->rhs()), it->second, collection, argVarsLinearForm, messages, point);
isLeft ? par->setLhs(copy) : par->setRhs(copy);
}
}
else
{
auto expS = exp->symbol();
string globalName;
vector<SgSymbol*> allInCommon;
int globalType = isGlobal(st, expS, &allInCommon, &globalName);
if (globalType == 0)
{
auto it = locVars.find(varName);
if (it == locVars.end())
{
auto symb = createSymbAndDecl(funcName, varName, expS, newSymbols);
it = locVars.insert(it, make_pair(varName, symb));
if (varName == resultName && !newHedrSymb)
newHedrSymb = symb;
if (newHedrSymb != symb)
{
auto arrType = isSgArrayType(symb->type());
if (arrType)
{
auto allList = arrType->getDimList();
while (allList)
{
auto list = allList;
if (list && list->lhs())
replaceSymbInExp(NULL, list->lhs(), list, -1, true, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, argVarsLinearForm, messages, point);
allList = allList->rhs();
}
}
}
}
exp->setSymbol(*it->second);
}
else
detectTypeOfSymbol(funcName, expS, globalType, newSymbols, allInCommon, globalName);
}
}
}
}
inline static void replaceSymbInStat(SgStatement* st, SgStatement* tempHedr,
const map<string, SgExpression*>& argVars, map<string, SgSymbol*>& locVars, set<SgSymbol*>& newSymbols,
const string& funcName, const string& resultName, SgSymbol*& newHedrSymb, map<SgExpression*, string>& collection,
map<string, vector<pair<SgSymbol*, SgExpression*>>>& argVarsLinearForm,
map<string, vector<Messages>>& messages, const PointCall& point)
{
if (st->variant() == SPF_PARALLEL_REG_DIR)
return;
if (st->symbol() && st->variant() != PROC_STAT)
{
auto s = st->symbol();
const string varName = s->identifier();
auto it = argVars.find(varName);
if (it != argVars.end())
st->setSymbol(*it->second->symbol());
else
{
string globalName;
vector<SgSymbol*> allInCommon;
int globalType = isGlobal(st, s, &allInCommon, &globalName);
if (globalType == 0)
{
auto it = locVars.find(varName);
if (it == locVars.end())
{
auto symb = createSymbAndDecl(funcName, varName, s, newSymbols);
it = locVars.insert(it, make_pair(varName, symb));
if (varName == resultName && !newHedrSymb)
newHedrSymb = symb;
}
st->setSymbol(*it->second);
}
else
detectTypeOfSymbol(funcName, s, globalType, newSymbols, allInCommon, globalName);
}
}
for (int i = 0; i < 3; ++i)
replaceSymbInExp(st, st->expr(i), NULL, i, false, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, argVarsLinearForm, messages, point);
}
static inline void remapVars(SgStatement* tempHedr,
map<string, SgExpression*> argVars, map<string, SgSymbol*>& locVars,
set<SgSymbol*>& newSymbols, const string& funcName, const string& resultName,
SgSymbol*& newHedrSymb, map<string, vector<Messages>>& messages, const PointCall& point)
{
map<SgExpression*, string> collection;
map<string, vector<pair<SgSymbol*, SgExpression*>>> argVarsLinearForm;
for (auto st = tempHedr; st != tempHedr->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (st->variant() == ENTRY_STAT) // exclude same argVars
{
if (st->symbol())
{
SgExpression* parList = st->expr(0);
for (SgExpression* p = parList; p; p = p->rhs())
{
string parName = p->lhs()->symbol()->identifier();
if (argVars.find(parName) != argVars.end())
argVars.erase(parName);
}
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
if (isSgExecutableStatement(st))
replaceSymbInStat(st, tempHedr, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, argVarsLinearForm, messages, point);
else
{
if (st->variant() == DATA_DECL)
dataDeclsByFunc[make_pair(funcName, current_file_id)].insert((SgValueExp*)st->expr(0));
else if (st->variant() == VAR_DECL_90 || st->variant() == VAR_DECL)
{
SgExpression* list = st->expr(0);
while (list)
{
auto ex = list->lhs();
if (ex->variant() == ASSGN_OP)
{
SgExpression* tmp = new SgExprListExp();
map<string, vector<pair<SgSymbol*, SgExpression*>>> dummy;
auto copy = ex->rhs()->copyPtr();
tmp->setLhs(copy);
replaceSymbInExp(NULL, tmp->lhs(), tmp, -1, true, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, dummy, messages, point);
dataDeclsByFuncS[make_pair(funcName, current_file_id)][OriginalSymbol(ex->lhs()->symbol())->identifier()] = copy;
}
list = list->rhs();
}
}
}
}
if (argVarsLinearForm.size())
{
SgStatement* lastDecl = tempHedr;
for (auto st = tempHedr; st != tempHedr->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
auto next = st->lexNext();
if (next && isSgExecutableStatement(next))
{
lastDecl = st;
break;
}
}
SgExpression* tmp = new SgExprListExp();
map<string, vector<pair<SgSymbol*, SgExpression*>>> dummy;
for (auto& bySymb : argVarsLinearForm)
{
for (auto& elem : bySymb.second)
{
newSymbols.insert(elem.first);
checkSymbols(current_file_id, newSymbols);
tmp->setLhs(elem.second);
replaceSymbInExp(NULL, tmp->lhs(), tmp, -1, true, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, collection, dummy, messages, point);
SgAssignStmt* init = new SgAssignStmt(*new SgVarRefExp(elem.first), *tmp->lhs());
lastDecl->insertStmtAfter(*init, *tempHedr);
}
}
}
}
static void addComment(SgStatement* st, bool isStart, string ident)
{
string comments = "";
if (st->comments())
{
comments = st->comments();
if (isStart)
comments += "![INLINING] start of '" + ident + "'\n";
else
comments = "![INLINING] end of '" + ident + "'\n" + comments;
}
else
comments = (isStart ? "![INLINING] start of '" : "![INLINING] end of '") + ident + "'\n";
st->setComments(comments.c_str());
}
static void insert(SgStatement* callSt, SgStatement* tempHedr, SgStatement* begin, SgSymbol* newHedrSymb,
vector<SgStatement*>& toDelete, set<SgStatement*>& useStats)
{
auto prev = callSt->lexPrev();
auto last = tempHedr->lastNodeOfStmt();
auto firstExec = begin->lexNext();
auto lastExec = callSt->lexNext();
while (lastExec && lastExec->variant() == GLOBAL) // bounds marker
lastExec = lastExec->lexNext();
vector<SgStatement*> formats;
for (; firstExec && firstExec != tempHedr->lastNodeOfStmt(); firstExec = firstExec->lexNext())
{
if (firstExec->variant() == USE_STMT)
useStats.insert(firstExec->copyPtr());
if (isSgExecutableStatement(firstExec))
break;
if (firstExec->variant() == FORMAT_STAT)
formats.push_back(firstExec->copyPtr());
}
checkNull(firstExec, convertFileName(__FILE__).c_str(), __LINE__);
tempHedr->extractStmt();
SgLabel* callLabel = callSt->label();
prev->insertStmtAfter(*firstExec, *callSt->controlParent());
auto next = prev->lexNext();
if (callSt->comments())
{
2024-02-25 11:16:56 +03:00
string callCom(callSt->comments());
if (next->comments()) {
string newCom = callCom + next->comments();
next->setComments(newCom.c_str());
}
2023-09-14 19:43:13 +03:00
else
2024-02-25 11:16:56 +03:00
next->addComment(callCom.c_str());
callSt->delComments();
2023-09-14 19:43:13 +03:00
}
auto ident = string(tempHedr->symbol()->identifier());
addComment(next, true, ident);
addComment(lastExec, false, ident);
if (callLabel)
{
if (firstExec->label())
{
SgContinueStmt* contSt = new SgContinueStmt();
contSt->setLabel(*callLabel);
prev->insertStmtAfter(*contSt, *callSt->controlParent());
}
else
firstExec->setLabel(*callLabel);
if (callSt->variant() != PROC_STAT) // function calls
callSt->deleteLabel(true);
}
for (auto &fmt : formats)
prev->insertStmtAfter(*fmt, *callSt->controlParent());
for (auto st = prev->lexNext(); st != callSt; st = st->lexNext())
{
if (st->lineNumber() > 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
st->setlineNumber(getNextNegativeLineNumber());
}
next = prev->lexNext();
next->setlineNumber(callSt->lineNumber());
next->setFileName(callSt->fileName());
2023-09-14 19:43:13 +03:00
last->extractStmt();
if (callSt->variant() == PROC_STAT)
toDelete.push_back(callSt);
else
{
callSt->setExpression(1, new SgExpression(VAR_REF));
callSt->expr(1)->setSymbol(newHedrSymb);
}
}
static int clean(const string& funcName, SgStatement* funcSt, const map<string, FuncInfo*>& funcMap, vector<SgStatement*>& toDelete)
{
// site-independent transformation
int gotoLabelId = -1;
SgLabel* contLab = NULL;
SgStatement* cont = NULL;
// return goto label if entry function is called
auto it = funcMap.find(funcName);
if (it != funcMap.end() && it->second->funcPointer->variant() == ENTRY_STAT)
gotoLabelId = getNextFreeLabel();
vector<SgStatement*> insertBeforeEnd;
// TODO: move all ENTRY points to the top of the subprogram
for (auto st = funcSt; st != funcSt->lastNodeOfStmt()->lexNext(); st = st->lexNext())
{
switch (st->variant())
{
case ENTRY_STAT:
{
SgLabel* gotoLab = new SgLabel(getNextFreeLabel());
SgContinueStmt* contSt = new SgContinueStmt();
contSt->setLabel(*gotoLab);
st->insertStmtBefore(*contSt, *st->controlParent());
// return goto label if entry function is called
if (st->symbol()->identifier() == funcName)
gotoLabelId = gotoLab->getLabNumber();
toDelete.push_back(st);
break;
}
case RETURN_STAT:
{
if (st->lexNext()->variant() == CONTROL_END && funcSt->lastNodeOfStmt() == st->lexNext())
{
if (st->label())
{
SgStatement* cont = new SgStatement(CONT_STAT);
cont->setLabel(*st->label());
st->insertStmtBefore(*cont, *st->controlParent());
}
toDelete.push_back(st);
break;
}
if (!cont) // create CONT_STAT
{
contLab = new SgLabel(getNextFreeLabel());
cont = new SgStatement(CONT_STAT);
cont->setLabel(*contLab);
insertBeforeEnd.push_back(cont);
}
SgGotoStmt* gotoSt = new SgGotoStmt(*contLab);
st->insertStmtBefore(*gotoSt, *st->controlParent());
toDelete.push_back(st);
break;
}
default:
break;
}
}
std::reverse(insertBeforeEnd.begin(), insertBeforeEnd.end());
for (auto& beforeEnd : insertBeforeEnd)
funcSt->lastNodeOfStmt()->insertStmtBefore(*beforeEnd, *funcSt);
return gotoLabelId;
}
// true if inserted
static inline bool insert(SgStatement* callSt, SgStatement* funcStat, SgExpression* args, set<SgSymbol*>& newSymbols,
const map<string, FuncInfo*>& funcMap, vector<SgStatement*>& toDelete, set<SgStatement*>& useStats,
map<string, vector<Messages>>& messages, const PointCall& point)
{
SgSymbol* funcSymb = funcStat->symbol();
bool isEntry = false;
SgSymbol* entrySymb = NULL;
SgStatement* tempHedr = NULL;
SgSymbol* tempSymb = NULL;
2023-11-28 12:58:22 +03:00
__spf_print(DEB, "------creating template------\n");
2023-09-14 19:43:13 +03:00
// 2.a create function template
auto funcSt = funcSymb->body();
if (funcSt->variant() == ENTRY_STAT)
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
//TODO:
isEntry = true;
entrySymb = funcSymb;
while (funcSt && funcSt->variant() != FUNC_HEDR)
funcSt = funcSt->lexPrev();
checkNull(funcSt, convertFileName(__FILE__).c_str(), __LINE__);
funcSymb = funcSt->symbol();
}
// insert template after global statement in current file
tempHedr = duplicateProcedure(funcStat, NULL, true, false, false);
tempSymb = tempHedr->symbol();
if (string(tempSymb->identifier()) != funcSymb->identifier())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
// set first inserting statement
SgStatement* begin = NULL;
if (isEntry)
{
for (auto st = tempHedr; st != tempHedr->lastNodeOfStmt(); st = st->lexNext())
if (st->variant() == ENTRY_STAT && st->symbol()->identifier() == string(entrySymb->identifier()))
begin = st;
}
else
begin = tempHedr;
checkNull(begin, convertFileName(__FILE__).c_str(), __LINE__);
// create map of arguments
SgSymbol* newHedrSymb = NULL; // requires for function with return variable
map<string, SgExpression*> argVars = createMapOfArgs(tempHedr, args); // local argument variable -> top argument variable
map<string, SgSymbol*> locVars; // local varname -> new local var
const string funcName = begin->symbol()->identifier();
string resultName = funcName;
if (isSgFuncHedrStmt(begin))
if (begin->expr(0) && begin->expr(0)->symbol())
resultName = begin->expr(0)->symbol()->identifier();
remapVars(tempHedr, argVars, locVars, newSymbols, funcName, resultName, newHedrSymb, messages, point);
if (!newHedrSymb && tempSymb->variant() == FUNCTION_NAME) // if no textual use of return variable, create new anyway
newHedrSymb = createSymbAndDecl("null", string(tempSymb->identifier()) + "_spf", tempSymb, newSymbols);
if (newHedrSymb)
{
//set clear name for module symbols
const string clearName = getClearName(newHedrSymb->identifier());
if (clearName != newHedrSymb->identifier())
newHedrSymb->changeName(clearName.c_str());
}
// clean function
int gotoLabId = clean(funcSymb->identifier(), tempHedr, funcMap, toDelete);
if (gotoLabId != -1)
{
SgLabel* gotoLab = new SgLabel(gotoLabId);
SgGotoStmt* gotoSt = new SgGotoStmt(*gotoLab);
callSt->insertStmtBefore(*gotoSt, *callSt->controlParent());
}
// insert template
insert(callSt, tempHedr, begin, newHedrSymb, toDelete, useStats);
return true;
}
static inline void replaceCall(SgExpression* exp, SgExpression* par, const int i, const bool lhs,
SgStatement* callSt, set<SgSymbol*>& newSymbols, SgStatement* insertPlace)
{
// create new call variable for this call and its declaration
SgSymbol* v = createSymbAndDecl("null", "arg", exp->symbol(), newSymbols);
SgAssignStmt* assign = new SgAssignStmt(*new SgVarRefExp(*v), *exp->copyPtr());
assign->setlineNumber(getNextNegativeLineNumber());
2023-11-22 20:21:18 +03:00
assign->setLocalLineNumber(callSt->lineNumber());
2023-09-14 19:43:13 +03:00
insertPlace->insertStmtBefore(*assign, *callSt->controlParent());
// replace function call to a new variable
if (!par)
callSt->setExpression(i, new SgVarRefExp(*v));
else
lhs ? par->setLhs(new SgVarRefExp(*v)) : par->setRhs(new SgVarRefExp(*v));
}
2023-11-22 20:21:18 +03:00
static void recFindFuncCall(FuncInfo* currentFuncI,
SgExpression* exp, SgExpression* par, const int i, const bool lhs,
2023-09-14 19:43:13 +03:00
const string& funcName, bool& foundCall,
SgStatement* callSt, set<SgSymbol*>& newSymbols, SgStatement* insertPlace)
{
if (exp)
{
2023-11-22 20:21:18 +03:00
recFindFuncCall(currentFuncI, exp->rhs(), exp, i, false, funcName, foundCall, callSt, newSymbols, insertPlace);
recFindFuncCall(currentFuncI, exp->lhs(), exp, i, true, funcName, foundCall, callSt, newSymbols, insertPlace);
2023-09-14 19:43:13 +03:00
2023-11-22 20:21:18 +03:00
if (exp->variant() == FUNC_CALL && exp->symbol() &&
currentFuncI->getCallName(make_pair(exp, exp->variant()), exp->symbol()->identifier(), callSt->lineNumber()) == funcName)
2023-09-14 19:43:13 +03:00
{
foundCall = true;
if (par) // do not extract external func call
replaceCall(exp, par, i, lhs, callSt, newSymbols, insertPlace);
}
}
}
static int ParameterType(SgExpression* exp, SgStatement* st)
{
if (isSgVarRefExp(exp) || // scalar variable
isSgArrayRefExp(exp) || // array variable
exp->variant() == CONST_REF || // symbol (named) constant
isSgValueExp(exp))// && exp->type()->variant() != T_STRING) // literal constant
return 1;
return 0;
}
static inline void PrecalculateExpression(SgSymbol* sp, SgExpression* e, SgStatement* stmt)
{
SgStatement* newst;
newst = new SgAssignStmt(*new SgVarRefExp(sp), *e);
newst->setlineNumber(getNextNegativeLineNumber());
stmt->insertStmtBefore(*newst, *stmt->controlParent());
}
static SgType* SgTypeFromFile(SgFile* f, int type)
{
SgType* t;
for (t = f->firstType(); t; t = t->next())
if (t->variant() == type)
return t;
return new SgType(type);
}
//TODO: more types
static SgType* getTrueType(SgType* inExp, parF funcParType)
{
if (funcParType == SCALAR_FLOAT_T)
return SgTypeFloat();
else if (funcParType == SCALAR_DOUBLE_T)
return SgTypeDouble();
else if (funcParType == SCALAR_CMPLX_FLOAT_T)
return SgTypeFromFile(current_file, T_COMPLEX);
else if (funcParType == SCALAR_CMPLX_DOUBLE_T)
return SgTypeFromFile(current_file, T_DCOMPLEX);
else
return inExp;
}
2023-11-22 20:21:18 +03:00
static inline void PrecalculateActualParameters(SgStatement* st, SgExpression* e,
2023-09-14 19:43:13 +03:00
const FuncInfo* func, set<SgSymbol*>& newSymbols)
{
// Precalculate actual parameter expressions
// e - actual parameter list
SgExpression* el;
SgSymbol* sp;
if (!e)
return;
//TODO: added exclude list!
//if (is_NoExpansionFunction(s))
//return;
int i = 0;
for (el = e; el; el = el->rhs(), i++)
{
switch (ParameterType(el->lhs(), st))
{
case 1:
break; // actual parameter can be accessed by reference
//case 2: PrecalculateSubscripts(el->lhs(),stmt); break;
default:
sp = createSymbAndDecl("null", "arg", NULL, newSymbols, getTrueType(el->lhs()->type(), func->funcParams.parametersT[i]));
PrecalculateExpression(sp, el->lhs(), st); //to support access by reference
el->setLhs(new SgVarRefExp(sp)); //replace actual parameter expression by 'sp' reference
break;
}
}
}
static void renameArgs(SgExpression* ex, const map<string, string>& remapArgs)
{
if (ex)
{
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)
{
auto s = ex->symbol();
if (s)
{
auto it = remapArgs.find(s->identifier());
if (it != remapArgs.end())
ex->setSymbol(findSymbolOrCreate(current_file, it->second, s->type()));
}
}
renameArgs(ex->lhs(), remapArgs);
renameArgs(ex->rhs(), remapArgs);
}
}
static void renameArgsIfGlobalNameIntersection(FuncInfo* func, const set<string>& globalNames)
{
if (func->isMain)
return;
map<string, string> remapArgs;
for (auto& par : func->funcParams.identificators)
{
if (globalNames.find(par) != globalNames.end())
{
int tmp = 0;
string newName = "";
do {
newName = par + to_string(tmp++);
} while (globalNames.find(newName) != globalNames.end());
remapArgs[par] = newName;
par = newName;
}
}
if (remapArgs.size() == 0)
return;
auto header = func->funcPointer->GetOriginal();
auto last = header->lastNodeOfStmt();
for (SgStatement* st = header->lexNext(); st != last; st = st->lexNext())
for (int z = 0; z < 3; ++z)
renameArgs(st->expr(z), remapArgs);
2023-11-28 12:58:22 +03:00
auto prog = isSgProcHedrStmt(header);
2023-09-14 19:43:13 +03:00
PTR_SYMB listP = SYMB_FUNC_PARAM(BIF_SYMB(prog->thebif));
vector<PTR_SYMB> newElems;
for (int p = 0; p < prog->numberOfParameters(); ++p)
{
SgSymbol* par = prog->parameter(p);
auto it = remapArgs.find(par->identifier());
if (it != remapArgs.end())
{
2023-11-28 12:58:22 +03:00
SgSymbol* replace = par->copyPtr();
replace->changeName(it->second.c_str());
2023-09-14 19:43:13 +03:00
newElems.push_back(replace->thesymb);
}
else
2023-11-28 12:58:22 +03:00
newElems.push_back(duplicateSymbol(listP));
2023-09-14 19:43:13 +03:00
listP = SYMB_NEXT_DECL(listP);
}
listP = newElems[0];
PTR_SYMB p = listP;
for (int z = 1; z < newElems.size(); ++z)
{
SYMB_NEXT_DECL(p) = newElems[z];
p = SYMB_NEXT_DECL(p);
}
SYMB_FUNC_PARAM(BIF_SYMB(prog->thebif)) = listP;
}
static void findUsed(SgExpression* ex, set<string>& used)
{
if (ex)
{
if (ex->variant() == VAR_REF)
{
auto s = ex->symbol();
if (s)
used.insert(s->identifier());
}
findUsed(ex->lhs(), used);
findUsed(ex->rhs(), used);
}
}
static map<SgStatement*, set<string>> usedByFunc;
static bool run_inliner(const map<string, FuncInfo*>& funcMap, set<SgStatement*>& toInsert, map<string, vector<Messages>>& SPF_messages,
const string& fileName, const FuncInfo* func, map<SgStatement*, set<SgSymbol*>>& newSymbsToDeclare,
const PointCall& point,
const map<string, CommonBlock*>& commonBlocks)
{
bool isInlined = false;
const string& funcName = func->funcName;
set<string> globalNames;
for (auto& common : commonBlocks)
for (auto& var : common.second->getVariables())
globalNames.insert(var->getName());
for (auto& callSt : toInsert)
{
SgStatement* insertPlace = callSt;
2023-11-22 20:21:18 +03:00
SgProgHedrStmt* currentFunc = (SgProgHedrStmt*) getFuncStat(callSt);
2023-09-14 19:43:13 +03:00
if (usedByFunc.find(currentFunc) == usedByFunc.end())
{
set<string> used;
for (auto st = currentFunc->lexNext(); st != currentFunc->lastNodeOfStmt(); st = st->lexNext())
{
if (isSgExecutableStatement(st))
for (int z = 0; z < 3; ++z)
findUsed(st->expr(z), used);
if (st->variant() == CONTAINS_STMT)
break;
}
usedByFunc[currentFunc] = used;
}
2023-11-22 20:21:18 +03:00
auto itF = funcMap.find(currentFunc->nameWithContains());
2023-09-14 19:43:13 +03:00
if (itF == funcMap.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
2023-11-22 20:21:18 +03:00
FuncInfo* currentFuncI = itF->second;
renameArgsIfGlobalNameIntersection(currentFuncI, globalNames);
2023-09-14 19:43:13 +03:00
set<string> useStatsInFunc;
for (SgStatement* s = currentFunc; s != currentFunc->lastNodeOfStmt(); s = s->lexNext())
{
if (s->variant() == CONTAINS_STMT)
break;
if (s->variant() == USE_STMT)
useStatsInFunc.insert(s->unparse());
}
SgStatement* funcStat = func->funcPointer->GetOriginal();
if (funcStat->fileName() != fileName)
{
//get from shadow copies
auto itF = hiddenData.find(fileName);
if (itF == hiddenData.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const string fromFile = funcStat->fileName();
const int line = funcStat->lineNumber();
bool done = false;
for (auto& shadowFunc : itF->second)
{
if (shadowFunc->fileName() == fromFile && shadowFunc->lineNumber() == line)
{
funcStat = shadowFunc;
done = true;
break;
}
}
if (!done)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
set<SgSymbol*> newSymbols;
bool foundCall = false;
if (!callSt || !isSgExecutableStatement(callSt))
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"It is allowed to inline function only at execution code section.");
__spf_printToLongBuf(messageR, R177);
2023-09-14 19:43:13 +03:00
getObjectForFileFromMap(fileName.c_str(), SPF_messages).push_back(Messages(ERROR, insertPlace->lineNumber(), messageR, messageE, 2011));
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
2023-11-28 12:58:22 +03:00
__spf_print(DEB, "------start inliner-----\n");
__spf_print(DEB, "---statement preprocessing---\n");
2023-09-14 19:43:13 +03:00
//simple convertation
if (callSt->controlParent()->variant() == LOGIF_NODE)
LogIftoIfThen(callSt->controlParent());
SgStatement* begin = callSt->lexPrev();
SgStatement* end = callSt->lexNext();
// 1.a: make statement preprocessing
// if call statement contains several inlining functions, split every such call
for (int i = 0; i < 3; ++i)
2023-11-22 20:21:18 +03:00
recFindFuncCall(currentFuncI, callSt->expr(i), NULL, i, false, funcName, foundCall, callSt, newSymbols, insertPlace);
2023-09-14 19:43:13 +03:00
2023-11-28 12:58:22 +03:00
__spf_print(DEB, "---argument preprocessing---\n");
2023-09-14 19:43:13 +03:00
// 1.b: make argument preprocessing
checkNull(begin, convertFileName(__FILE__).c_str(), __LINE__);
// if call statement has any expression as its artument, split this expression for separate statement
// if call statement has any function as its argument, split this call
for (auto st = begin->lexNext(); st != end; st = st->lexNext())
{
if (st->variant() == ASSIGN_STAT)
{
2023-11-22 20:21:18 +03:00
auto rPart = st->expr(1);
int line = st->lineNumber() < 0 ? st->localLineNumber() : st->lineNumber();
if (rPart->variant() == FUNC_CALL && rPart->symbol() &&
currentFuncI->getCallName(make_pair(rPart, rPart->variant()), rPart->symbol()->identifier(), line) == funcName)
{
2023-09-14 19:43:13 +03:00
if (isSgVarRefExp(st->expr(0)) || isSgArrayRefExp(st->expr(0)) && !isSgArrayType(st->expr(0)->type()))
2023-11-22 20:21:18 +03:00
PrecalculateActualParameters(st, st->expr(1)->lhs(), func, newSymbols);
}
2023-09-14 19:43:13 +03:00
}
else if (st->variant() == PROC_STAT)
{
2023-11-22 20:21:18 +03:00
if (st->symbol() &&
currentFuncI->getCallName(make_pair(st, st->variant()), st->symbol()->identifier(), st->lineNumber()) == funcName)
2023-09-14 19:43:13 +03:00
{
foundCall = true;
if (st->expr(0))
2023-11-22 20:21:18 +03:00
PrecalculateActualParameters(st, st->expr(0), func, newSymbols);
2023-09-14 19:43:13 +03:00
}
}
}
set<SgStatement*> useStats;
2023-11-28 12:58:22 +03:00
__spf_print(DEB, "---start inlining---\n");
2023-09-14 19:43:13 +03:00
// 2. create function template to modify and insert it
if (foundCall)
{
bool change = true;
while (change)
{
change = false;
vector<SgStatement*> toDelete;
for (auto st = begin->lexNext(); st != end; st = st->lexNext())
{
switch (st->variant())
{
case ASSIGN_STAT:
{
2023-11-22 20:21:18 +03:00
auto rPart = st->expr(1);
int line = st->lineNumber() < 0 ? st->localLineNumber() : st->lineNumber();
if (rPart->variant() == FUNC_CALL && rPart->symbol() &&
currentFuncI->getCallName(make_pair(rPart, rPart->variant()), rPart->symbol()->identifier(), line) == funcName)
{
bool doInline = insert(st, funcStat, rPart->lhs(), newSymbols, funcMap, toDelete, useStats, SPF_messages, point);
change |= doInline;
isInlined |= doInline;
}
2023-09-14 19:43:13 +03:00
}
2023-11-22 20:21:18 +03:00
break;
2023-09-14 19:43:13 +03:00
case PROC_STAT:
2023-11-22 20:21:18 +03:00
if (st->symbol() &&
currentFuncI->getCallName(make_pair(st, st->variant()), st->symbol()->identifier(), st->lineNumber()) == funcName)
2023-09-14 19:43:13 +03:00
{
bool doInline = insert(st, funcStat, st->expr(0), newSymbols, funcMap, toDelete, useStats, SPF_messages, point);
change |= doInline;
isInlined |= doInline;
}
2023-11-22 20:21:18 +03:00
break;
2023-09-14 19:43:13 +03:00
default:
2023-11-22 20:21:18 +03:00
break;
2023-09-14 19:43:13 +03:00
}
}
for (auto& st : toDelete)
st->extractStmt();
}
}
for (auto& use : useStats)
{
string currUse = use->unparse();
if (useStatsInFunc.find(currUse) == useStatsInFunc.end())
{
useStatsInFunc.insert(currUse);
currentFunc->insertStmtAfter(*use, *currentFunc);
}
}
checkSymbols(currentFunc->getFileId(), newSymbols);
for (auto& symb : newSymbols)
{
if (symb->variant() == CONSTRUCT_NAME)
continue;
newSymbsToDeclare[currentFunc].insert(symb);
}
}
return isInlined;
}
static vector<pair<SgStatement*, SgStatement*>> getNextBounds(SgStatement* point)
{
vector<pair<SgStatement*, SgStatement*>> parts;
pair<SgStatement*, SgStatement*> newPart;
bool sectionStarted = false;
for (auto st = point; st != point->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (st->variant() == GLOBAL)
{
if (!sectionStarted)
{
newPart.first = st;
sectionStarted = true;
}
else if (sectionStarted)
{
newPart.second = st;
parts.push_back(newPart);
sectionStarted = false;
}
}
}
if (sectionStarted)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return parts;
}
static bool dontInlineByAttribute(SgStatement* st)
{
bool dontInline = false;
for (int k = 0; k < st->numberOfAttributes(); ++k)
if (st->getAttribute(k)->getAttributeType() == BOOL_VAL)
dontInline = true;
if (dontInline)
__spf_print(1, " skip call in statement with line %d by attribute\n", st->lineNumber());
return dontInline;
}
static void fillNewFunctions(SgExpression* ex, SgStatement* main,
map<FuncInfo*, set<SgStatement*>>& nextInfo,
const map<string, FuncInfo*>& funcMap)
{
if (ex)
{
if (ex->variant() == FUNC_CALL)
if (funcMap.find(ex->symbol()->identifier()) != funcMap.end())
if (!dontInlineByAttribute(main))
nextInfo[funcMap.at(ex->symbol()->identifier())].insert(main);
fillNewFunctions(ex->lhs(), main, nextInfo, funcMap);
fillNewFunctions(ex->rhs(), main, nextInfo, funcMap);
}
}
static void fillNewFunctions(SgStatement* begin, SgStatement* end,
map<FuncInfo*, set<SgStatement*>>& nextInfo,
const map<string, FuncInfo*>& funcMap)
{
for (auto st = begin; st != end; st = st->lexNext())
{
if (st->variant() == PROC_STAT)
if (funcMap.find(st->symbol()->identifier()) != funcMap.end())
if (!dontInlineByAttribute(st))
nextInfo[funcMap.at(st->symbol()->identifier())].insert(st);
for (int z = 0; z < 3; ++z)
fillNewFunctions(st->expr(z), st, nextInfo, funcMap);
}
}
static map<FuncInfo*, set<SgStatement*>> fillNextDeep(const set<SgStatement*>& insertedIn, const map<string, FuncInfo*>& funcMap)
{
map<FuncInfo*, set<SgStatement*>> nextInfo;
for (auto& point : insertedIn)
for (auto& part : getNextBounds(point))
fillNewFunctions(part.first, part.second, nextInfo, funcMap);
return nextInfo;
}
static void addMessage(bool status, map<string, vector<Messages>>& SPF_messages, const string& fileName, const int line)
{
if (status == true)
return;
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Function inlining failed with an error.");
__spf_printToLongBuf(messageR, R193);
getObjectForFileFromMap(fileName.c_str(), SPF_messages).push_back(Messages(ERROR, line, messageR, messageE, 2020));
}
2023-11-26 18:57:05 +03:00
static bool inliner(const string& fileName_in, const string& funcName, const int lineNumber,
const map<string, vector<FuncInfo*>>& allFuncInfo, map<string, vector<Messages>>& SPF_messages,
map<SgStatement*, set<SgSymbol*>>& newSymbsToDeclare, const map<string, CommonBlock*>& commonBlocks,
int deepLvl = 0)
2023-11-28 12:58:22 +03:00
{
2023-09-14 19:43:13 +03:00
map<string, FuncInfo*> funcMap;
createMapOfFunc(allFuncInfo, funcMap);
auto func = getFuncInfo(funcMap, funcName);
const string& fileName = (fileName_in == "") ? func->fileName : fileName_in;
if (func && !func->doNotInline)
{
if (SgFile::switchToFile(fileName) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
//TODO:
// now function is expected to be declared in the target file
set<SgStatement*> toInsert;
if (lineNumber > 0)
{
SgStatement* callSt = SgStatement::getStatementByFileAndLine(fileName, lineNumber);
if (callSt)
toInsert.insert(callSt);
}
else
{
for (auto& callTo : func->callsTo)
{
for (auto& callInfo : callTo->callsFromDetailed)
2023-09-14 19:43:13 +03:00
{
auto& callFrom = callInfo.detailCallsFrom;
2023-09-14 19:43:13 +03:00
if (callFrom.first == funcName)
{
SgStatement* callSt = SgStatement::getStatementByFileAndLine(fileName, callFrom.second);
if (callSt)
toInsert.insert(callSt);
}
}
}
}
set<SgStatement*> insertedIn;
set<SgStatement*> markers;
for (auto& elem : toInsert)
{
bool dontInline = dontInlineByAttribute(elem);
if (dontInline)
continue;
insertedIn.insert(getFuncStat(elem));
//insert bounds
auto cp = elem->controlParent();
auto boundAfter = new SgStatement(GLOBAL);
auto boundBefore = new SgStatement(GLOBAL);
elem->insertStmtBefore(*boundAfter, *cp);
elem->insertStmtAfter(*boundBefore, *cp);
markers.insert(boundAfter);
markers.insert(boundBefore);
}
if (markers.size() == 0)
2023-11-22 20:21:18 +03:00
return false;
2023-09-14 19:43:13 +03:00
PointCall point;
point.mainPoint.first = fileName;
point.mainPoint.second = lineNumber;
point.func = func;
point.currLvl = 0;
point.currCall = func->funcName;
2024-02-25 11:16:56 +03:00
__spf_print(1, " INLINE %s - ", func->funcName.c_str());
2023-09-14 19:43:13 +03:00
#ifdef _WIN32
sendMessage_2lvl(wstring(L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '") + wstring(func->funcName.begin(), func->funcName.end()) + L"'");
#else
sendMessage_2lvl(wstring(L"inlinig of function '") + wstring(func->funcName.begin(), func->funcName.end()) + L"'");
#endif
//1 level
bool isInlined = run_inliner(funcMap, toInsert, SPF_messages, fileName, func, newSymbsToDeclare, point, commonBlocks);
2024-02-25 11:16:56 +03:00
__spf_print(1, "%s\n", isInlined ? "done" : "fault");
addMessage(isInlined, SPF_messages, fileName, lineNumber);
2023-09-14 19:43:13 +03:00
2023-11-22 20:21:18 +03:00
if (isInlined == false)
{
__spf_print(1, " missing ...\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
2023-09-14 19:43:13 +03:00
if (deepLvl >= 0 && isInlined)
{
int currDeep = 0;
bool changed = true;
while (changed)
{
changed = false;
currDeep++;
if (deepLvl > 0 && deepLvl <= currDeep)
break;
for (auto& next : fillNextDeep(insertedIn, funcMap))
{
for (int p = 0; p < currDeep; ++p)
__spf_print(1, " ");
if (next.first->doNotInline)
{
__spf_print(1, "skip %s by flag\n", next.first->funcName.c_str());
continue;
}
point.currLvl = currDeep;
point.currCall = next.first->funcName;
2024-02-25 11:16:56 +03:00
__spf_print(1, " INLINE %s - ", next.first->funcName.c_str());
2023-09-14 19:43:13 +03:00
bool isInlined = run_inliner(funcMap, next.second, SPF_messages, fileName, next.first, newSymbsToDeclare, point, commonBlocks);
2024-02-25 11:16:56 +03:00
__spf_print(1, "%s\n", isInlined ? "done" : "fault");
addMessage(isInlined, SPF_messages, fileName, lineNumber);
2023-09-14 19:43:13 +03:00
changed |= isInlined;
}
}
}
for (auto& marker : markers)
marker->extractStmt();
}
return true;
}
2023-11-26 18:57:05 +03:00
static bool inliner(const string& allInFunc, const map<string, vector<FuncInfo*>>& allFuncInfo,
map<string, vector<Messages>>& SPF_messages,
map<SgStatement*, set<SgSymbol*>>& newSymbsToDeclare, const map<string, CommonBlock*>& commonBlocks,
int deepLvl = 0)
2023-09-14 19:43:13 +03:00
{
bool result = true;
map<string, FuncInfo*> funcMap;
createMapOfFunc(allFuncInfo, funcMap);
auto func = getFuncInfo(funcMap, allInFunc);
if (func && !func->doNotInline)
{
if (SgFile::switchToFile(func->fileName) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto& callInfo : func->callsFromDetailed)
2023-09-14 19:43:13 +03:00
{
auto& callFrom = callInfo.detailCallsFrom;
2023-09-14 19:43:13 +03:00
bool res = inliner(func->fileName, callFrom.first, callFrom.second, allFuncInfo, SPF_messages, newSymbsToDeclare, commonBlocks, deepLvl);
result = result && res;
}
}
return result;
}
static vector<SgSymbol*> sortConstRefs(const map<string, SgSymbol*>& constRefs)
{
map<SgSymbol*, set<string>> deps;
map<SgSymbol*, pair<string, int>> constRefByFunc; // value is <funcName, fileId>
for (auto& byF : replacedConstRef)
for (auto& s : byF.second)
constRefByFunc[s.second.first] = byF.first;
bool printInternal = false;
for (auto& elem : constRefs)
{
SgSymbol* s = elem.second;
if (constRefByFunc.find(s) == constRefByFunc.end())
{
__spf_print(1, " const not found '%s' with id %d\n", s->identifier(), s->id());
printInternal = true;
continue;
}
auto& inFunc = constRefByFunc[s];
map<string, pair<SgSymbol*, string>>& byFuncRefpl = replacedConstRef[inFunc];
deps[s] = set<string>();
set<SgSymbol*> tmp;
findAllConstRef(isSgConstantSymb(elem.second)->constantValue(), tmp);
for (auto& ref : tmp)
{
auto itS = byFuncRefpl.find(ref->identifier());
if (itS != byFuncRefpl.end())
{
auto newName = itS->second.second.c_str();
ref->changeName(newName);
deps[elem.second].insert(newName);
}
else
deps[s].insert(ref->identifier());
}
}
if (printInternal)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
set<string> added;
vector<SgSymbol*> result;
for (auto& elem : deps)
{
bool existInRef = false;
for (auto& dep : elem.second)
if (constRefs.find(dep) != constRefs.end())
existInRef = true;
if (!existInRef)
{
result.push_back(elem.first);
added.insert(elem.first->identifier());
}
}
while (result.size() != constRefs.size())
{
for (auto& elem : deps)
{
if (added.find(elem.first->identifier()) != added.end())
continue;
bool needToAdd = true;
for (auto& dep : elem.second)
if (added.find(dep) == added.end() && (dep != elem.first->identifier()))
needToAdd = false;
if (needToAdd)
{
result.push_back(elem.first);
added.insert(elem.first->identifier());
}
}
}
return result;
}
static pair<string, int> getCommonInfo(SgSymbol* toDec)
{
pair<string, int> info = make_pair("NULL", -1);
auto attrsC = getAttributes<SgSymbol*, char*>(toDec, set<int> { COMM_STAT });
if (attrsC.size() && attrsC.size() != 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (attrsC.size())
{
auto attrsPos = getAttributes<SgSymbol*, int*>(toDec, set<int> { COMM_LIST });
if (attrsPos.size() && attrsPos.size() != 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
info.first = attrsC[0];
info.second = *attrsPos[0];
}
return info;
}
static bool addNewCommonDecl(SgSymbol* toDec, const int posNum, const string& commName,
map<string, vector<SgExpression*>>& commonBlocksRef,
const map<string, CommonBlock*>& commonBlocks,
map<string, map<int, SgSymbol*>>& commons,
const string& needToRename)
{
if (posNum != -1)
{
if (needToRename != "")
toDec->changeName(needToRename.c_str());
auto itCommRef = commonBlocksRef.find(commName);
if (itCommRef == commonBlocksRef.end())
commons[commName][posNum] = toDec; // sort by position
else
{
auto it = commonBlocks.find(commName);
if (it == commonBlocks.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto groupedByPos = it->second->getGroupedVars();
auto itG = groupedByPos.find(posNum);
if (itG == groupedByPos.end() || itG != groupedByPos.end() && itG->second.size() == 1)
commons[commName][posNum] = toDec; // sort by position
else
{
int idx = 0;
SgExpression* ex = NULL;
for (auto& elem : itCommRef->second)
{
for (auto list = elem->lhs(); list && !ex; list = list->rhs(), ++idx)
if (idx == posNum)
ex = list->lhs();
if (ex)
break;
}
if (ex == NULL)
commons[commName][posNum] = toDec; // sort by position
else
{
if (ex->symbol() == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (ex->symbol()->identifier() != string(toDec->identifier()))
{
toDec->changeName(ex->symbol()->identifier());
return true;
}
else
commons[commName][posNum] = toDec; // sort by position
}
}
}
}
return false;
}
2023-11-26 18:57:05 +03:00
static void createDeclarations(const map<SgStatement*, set<SgSymbol*>>& newSymbsToDeclare, const map<string, CommonBlock*>& commonBlocks)
2023-09-14 19:43:13 +03:00
{
map<pair<string, int>, map<string, string>> preprocDataByFunc; // key is <funcName, int>
map<pair<string, int>, map<string, SgExpression*>> initValue;
for (auto& dataByF : dataDeclsByFunc)
preprocDataByFunc[dataByF.first] = splitData(dataByF.second);
for (auto& dataByF : dataDeclsByFuncS)
{
initValue[dataByF.first] = dataByF.second;
for (auto& elem : dataByF.second)
preprocDataByFunc[dataByF.first][elem.first] = "---";
}
map<SgSymbol*, pair<pair<string, int>, string>> originalInfo; // value is <<funcName, int>, sName>
for (auto& elem : createdByFunc)
for (auto& s : elem.second)
originalInfo[s.second] = make_pair(elem.first, s.first);
for (auto& byFunc : newSymbsToDeclare)
{
if (!byFunc.first->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
__spf_print(1, "symbols checking for function '%s'\n", byFunc.first->symbol()->identifier());
int currFileId = byFunc.first->getFileId();
checkSymbols(currFileId, byFunc.second);
map<string, vector<SgExpression*>> commonBlocksRef;
getCommonBlocksRef(commonBlocksRef, byFunc.first, byFunc.first ? byFunc.first->lastNodeOfStmt() : NULL);
map<string, map<string, vector<SgSymbol*>>> groups;
map<string, map<string, vector<SgSymbol*>>> groupsConstRefs;
map<string, map<int, SgSymbol*>> commons;
map<string, SgSymbol*> constRefs;
map<string, SgSymbol*> saveRefs;
map<SgSymbol*, string> declRefs;
map<SgSymbol*, SgExpression*> declInitInfo;
set<SgSymbol*> allocatable;
map<string, int> commonRenames;
SgStatement* place = byFunc.first;
while (isSgProgHedrStmt(place) == NULL && place->variant() != MODULE_STMT)
place = place->controlParent();
SgStatement* scope = place;
set<string> declared, undeclared;
map<string, set<string>> commonsInCurrFunc;
while (isSgExecutableStatement(place) == NULL && place != scope->lastNodeOfStmt())
{
if (place->variant() == VAR_DECL ||
place->variant() == VAR_DECL_90 ||
place->variant() == DIM_STAT)
{
for (auto list = place->expr(0); list; list = list->rhs())
{
auto elem = list->lhs();
if (elem && elem->symbol())
declared.insert(elem->symbol()->identifier());
}
}
else if (place->variant() == COMM_STAT)
{
for (SgExpression* exp = place->expr(0); exp; exp = exp->rhs())
{
string commonName = "spf_unnamed";
if (exp->symbol())
commonName = string(exp->symbol()->identifier());
for (auto list = exp->lhs(); list; list = list->rhs())
{
auto elem = list->lhs();
if (elem && elem->symbol())
{
declared.insert(elem->symbol()->identifier());
commonsInCurrFunc[commonName].insert(elem->symbol()->identifier());
}
}
}
}
else if (place->variant() == PARAM_DECL)
{
SgParameterStmt* param = (SgParameterStmt*)place;
for (int z = 0; z < param->numberOfConstants(); ++z)
declared.insert(param->constant(z)->identifier());
}
place = place->lexNext();
}
//find undeclared
auto usedVars = usedByFunc.find(byFunc.first);
if (usedVars != usedByFunc.end())
{
for (auto& var : usedVars->second)
if (declared.find(var) == declared.end())
undeclared.insert(var);
}
vector<SgSymbol*> toDeclV;
// firstly - not in common
for (auto& toDec : byFunc.second)
{
const auto commInfo = getCommonInfo(toDec);
const int posNum = commInfo.second;
if (posNum == -1)
toDeclV.push_back(toDec);
}
// secondly - in common
for (auto& toDec : byFunc.second)
{
const auto commInfo = getCommonInfo(toDec);
const int posNum = commInfo.second;
if (posNum != -1)
toDeclV.push_back(toDec);
}
if (toDeclV.size() != byFunc.second.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
map<string, map<int, set<SgSymbol*>>> alreadyCommonDecl;
for (auto& toDec : toDeclV)
{
bool isVarFromAnotherCommon = false;
string needToRename = "";
int globalType = -1;
if (declared.find(toDec->identifier()) != declared.end() || undeclared.find(toDec->identifier()) != undeclared.end())
{
const auto commInfo = getCommonInfo(toDec);
const int posNum = commInfo.second;
if (posNum == -1)
continue;
else
{
bool wasUnDeclared = undeclared.find(toDec->identifier()) != undeclared.end();
globalType = 1;
bool already = false;
if (alreadyCommonDecl.find(commInfo.first) != alreadyCommonDecl.end())
{
if (alreadyCommonDecl[commInfo.first].find(posNum) != alreadyCommonDecl[commInfo.first].end())
{
auto curr = string(toDec->identifier());
for (auto& s : alreadyCommonDecl[commInfo.first][posNum])
if (s->identifier() == curr)
already = true;
}
}
if (!already)
{
auto itC = commonsInCurrFunc.find(commInfo.first);
if (itC == commonsInCurrFunc.end())
{
for (auto& currC : commonBlocks)
{
if (currC.first == commInfo.first && !wasUnDeclared)
continue;
for (auto& var : currC.second->getVariables())
{
if (var->getName() == toDec->identifier())
{
const string name = var->getName();
if (commonRenames.find(name) == commonRenames.end())
commonRenames[name] = 0;
needToRename = name + "_cr" + to_string(commonRenames[name]);
commonRenames[name]++;
break;
}
}
if (needToRename != "")
break;
}
}
if (itC != commonsInCurrFunc.end())
if (itC->second.find(toDec->identifier()) != itC->second.end())
continue;
isVarFromAnotherCommon = true;
alreadyCommonDecl[commInfo.first][posNum].insert(toDec);
}
}
}
else
{
declared.insert(toDec->identifier());
const auto commInfo = getCommonInfo(toDec);
const int posNum = commInfo.second;
if (posNum != -1)
{
alreadyCommonDecl[commInfo.first][posNum].insert(toDec);
globalType = 1;
isVarFromAnotherCommon = true;
}
}
if (isSgConstantSymb(toDec))
constRefs[toDec->identifier()] = toDec;
if (toDec->attributes())
{
if ((toDec->attributes() & SAVE_BIT) || (toDec->attributes() & DATA_BIT))
if (globalType != 1) // not in COMMON
saveRefs[toDec->identifier()] = toDec;
2024-01-23 13:04:46 +03:00
if (isAllocated(toDec))
2023-09-14 19:43:13 +03:00
allocatable.insert(toDec);
if (toDec->attributes() & DATA_BIT)
{
auto itD = originalInfo.find(toDec);
if (itD == originalInfo.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto itDF = preprocDataByFunc.find(itD->second.first);
if (itDF == preprocDataByFunc.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (initValue.find(itD->second.first) == initValue.end())
{
auto info = itDF->second.find(itD->second.second);
if (info == itDF->second.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
declRefs[toDec] = info->second;
}
else
{
auto itDF = initValue[itD->second.first];
auto info = itDF.find(itD->second.second);
if (info == itDF.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
declInitInfo[toDec] = info->second;
}
}
}
globalType = (globalType == -1) ? isGlobal(byFunc.first, toDec) : globalType;
if (globalType != 0 && !isVarFromAnotherCommon)
continue;
else
{
const auto commInfo = getCommonInfo(toDec);
const int posNum = commInfo.second;
const string commName = commInfo.first;
bool needContinue = addNewCommonDecl(toDec, posNum, commName, commonBlocksRef, commonBlocks, commons, needToRename);
if (needContinue)
continue;
auto attrsM = getAttributes<SgSymbol*, char*>(toDec, set<int> { MODULE_STMT });
if (attrsM.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
string newDecl = makeDeclaration(NULL, { toDec })->unparse();
auto it = newDecl.find("::");
if (it == string::npos)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (isSgConstantSymb(toDec))
groupsConstRefs[newDecl.substr(0, it)][toDec->identifier()].push_back(toDec);
else
groups[newDecl.substr(0, it)][toDec->identifier()].push_back(toDec);
}
//insert PARAMETER
if (constRefs.size())
{
for (auto& toDecls : groupsConstRefs)
{
vector<SgSymbol*> unitedList;
for (auto& elem : toDecls.second)
unitedList.push_back(elem.second[0]);
makeDeclaration(byFunc.first, unitedList);
}
SgParameterStmt* param = new SgParameterStmt();
for (auto& elem : sortConstRefs(constRefs))
param->addConstant(elem);
2024-07-19 21:10:43 +03:00
param->setlineNumber(place->lineNumber());
2023-09-14 19:43:13 +03:00
place->insertStmtBefore(*param, *scope);
}
for (auto& toDecls : groups)
{
vector<SgSymbol*> unitedList;
vector<SgExpression*> inits;
for (auto& elem : toDecls.second)
{
unitedList.push_back(elem.second[0]);
auto initI = declInitInfo.find(elem.second[0]);
if (initI != declInitInfo.end())
inits.push_back(initI->second);
else
inits.push_back(NULL);
}
auto inserted = makeDeclaration(byFunc.first, unitedList, &inits);
SgExpression* list = inserted->expr(0);
bool typeConverted = false;
while (list)
{
if (list->lhs())
{
if (!typeConverted)
{
typeConverted = true;
SgType* t = list->lhs()->symbol()->type();
if (t->selector())
{
if (t->selector()->variant() == CONST_REF)
2024-04-09 11:51:21 +03:00
t->setSelector(CalculateInteger(t->selector()->copyPtr()));
2023-09-14 19:43:13 +03:00
}
if (t->length())
{
if (t->length()->variant() == CONST_REF)
{
2024-04-09 11:51:21 +03:00
auto result = CalculateInteger(t->length()->copyPtr());
2023-09-14 19:43:13 +03:00
if (result->variant() == INT_VAL)
t->setLength(result);
}
}
}
2024-04-09 11:51:21 +03:00
auto result = CalculateInteger(list->lhs()->copyPtr());
2023-09-14 19:43:13 +03:00
list->setLhs(result);
}
list = list->rhs();
}
}
vector<SgStatement*> newCommons;
for (auto& byCommon : commons)
{
vector<SgExpression*> refs;
for (auto& s : byCommon.second)
refs.push_back(new SgVarRefExp(s.second));
std::reverse(refs.begin(), refs.end());
SgStatement* common = new SgStatement(COMM_STAT);
common->setExpression(0, new SgExpression(COMM_LIST, makeExprList(refs, false), NULL, new SgSymbol(COMMON_NAME, byCommon.first.c_str())));
newCommons.push_back(common);
}
if (newCommons.size())
2024-07-19 21:10:43 +03:00
{
2023-09-14 19:43:13 +03:00
for (auto& elem : newCommons)
2024-07-19 21:10:43 +03:00
{
elem->setlineNumber(place->lineNumber());
2023-09-14 19:43:13 +03:00
place->insertStmtBefore(*elem, *scope);
2024-07-19 21:10:43 +03:00
}
}
2023-09-14 19:43:13 +03:00
//insert SAVE
if (saveRefs.size())
{
SgStatement* save = new SgStatement(SAVE_DECL);
vector<SgExpression*> refs;
for (auto& s : saveRefs)
refs.push_back(new SgVarRefExp(s.second));
save->setExpression(0, makeExprList(refs));
2024-07-19 21:10:43 +03:00
save->setlineNumber(place->lineNumber());
2023-09-14 19:43:13 +03:00
place->insertStmtBefore(*save, *scope);
}
if (declRefs.size())
{
SgStatement* decl = new SgStatement(DATA_DECL);
SgExpression* value = new SgExpression(STMT_STR);
string dataS = "data ";
int z = 0;
for (auto& elem : declRefs)
{
dataS += elem.first->identifier() + string("/") + elem.second + "/";
if (z != declRefs.size() - 1)
dataS += ",";
++z;
}
value->thellnd->entry.string_val = new char[dataS.size() + 1];
strcpy(value->thellnd->entry.string_val, dataS.c_str());
decl->setExpression(0, value);
2024-07-19 21:10:43 +03:00
decl->setlineNumber(place->lineNumber());
2023-09-14 19:43:13 +03:00
place->insertStmtBefore(*decl, *scope);
}
//insert ALLOCATABLE
if (allocatable.size())
{
2024-07-19 21:10:43 +03:00
SgStatement* alloc_stat = new SgStatement(ALLOCATABLE_STMT);
2023-09-14 19:43:13 +03:00
vector<SgExpression*> refs;
for (auto& s : allocatable)
refs.push_back(new SgVarRefExp(s));
2024-07-19 21:10:43 +03:00
alloc_stat->setExpression(0, makeExprList(refs));
alloc_stat->setlineNumber(place->lineNumber());
place->insertStmtBefore(*alloc_stat, *scope);
2023-09-14 19:43:13 +03:00
}
}
}
2023-11-26 18:57:05 +03:00
static void convertLinesToAbsolute(const map<string, vector<FuncInfo*>>& allFuncInfo,
vector<tuple<string, string, int>>& inDataProc)
{
2023-11-28 12:58:22 +03:00
set<tuple<string, string, int>> added;
2023-11-26 18:57:05 +03:00
for (int z = 0; z < inDataProc.size(); ++z)
{
if (std::get<2>(inDataProc[z]) > 0)
continue;
auto funcToInl = std::get<0>(inDataProc[z]);
auto file = std::get<1>(inDataProc[z]);
int absoluteLine = 0;
int shilftLine = -std::get<2>(inDataProc[z]);
2023-11-28 12:58:22 +03:00
2023-11-26 18:57:05 +03:00
for (auto& funcByFile : allFuncInfo)
{
if (funcByFile.first != file)
continue;
for (auto& func : funcByFile.second)
{
int targetLine = func->linesNum.first + shilftLine;
2023-11-28 12:58:22 +03:00
//__spf_print(1, "%s target %d + %d = %d\n", func->funcName.c_str(), func->linesNum.first, shilftLine, targetLine);
2023-11-26 18:57:05 +03:00
for (auto& detCall : func->callsFromDetailed)
{
2023-11-28 12:58:22 +03:00
if (detCall.detailCallsFrom == make_pair(funcToInl, targetLine) &&
added.find(make_tuple(file, funcToInl, targetLine)) == added.end())
2023-11-26 18:57:05 +03:00
{
2023-12-11 20:53:33 +03:00
__spf_print(1, "%s %d (was %d) %s\n", funcToInl.c_str(), targetLine, std::get<2>(inDataProc[z]), funcByFile.first.c_str());
2023-11-28 12:58:22 +03:00
added.insert(make_tuple(file, funcToInl, targetLine));
2023-11-26 18:57:05 +03:00
absoluteLine = targetLine;
break;
}
}
if (absoluteLine)
break;
}
2023-11-28 12:58:22 +03:00
if (absoluteLine)
break;
2023-11-26 18:57:05 +03:00
}
if (absoluteLine == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
std::get<2>(inDataProc[z]) = absoluteLine;
}
}
void callInliner(const map<string, vector<FuncInfo*>>& allFuncInfo,
vector<tuple<string, string, int>>& inDataProc,
map<string, set<pair<string, int>>>& inDataChains,
const set<string>& inDataChainsStart,
map<string, vector<Messages>>& SPF_messages,
const map<string, CommonBlock*>& commonBlocks)
{
map<SgStatement*, set<SgSymbol*>> newSymbsToDeclare;
map<string, FuncInfo*> tmpM;
createMapOfFunc(allFuncInfo, tmpM);
FuncInfo* mainF = NULL;
for (auto& elem : tmpM)
if (elem.second->isMain)
mainF = elem.second;
checkNull(mainF, convertFileName(__FILE__).c_str(), __LINE__);
#if 0
//inliner(mainF->funcName, allFuncInfo, SPF_messages, newSymbsToDeclare);
#else
if (inDataProc.size())
{
2023-11-28 12:58:22 +03:00
__spf_print(1, "count of inline data %ld\n", inDataProc.size());
2023-11-26 18:57:05 +03:00
convertLinesToAbsolute(allFuncInfo, inDataProc);
map<int, vector<int>> sortByLvl;
int maxLvlCall = 0;
for (int z = 0; z < inDataProc.size(); ++z)
{
if (std::get<2>(inDataProc[z]) != -1)
{
int lvl = getLvlCall(mainF, 0, std::get<0>(inDataProc[z]), std::get<1>(inDataProc[z]), std::get<2>(inDataProc[z]));
if (lvl == -1)
{
bool found = false;
for (auto& func : tmpM)
{
if (func.second->isMain)
continue;
int lvlTmp = getLvlCall(func.second, 0, std::get<0>(inDataProc[z]), std::get<1>(inDataProc[z]), std::get<2>(inDataProc[z]));
if (lvlTmp != -1)
lvl = std::max(lvl, lvlTmp);
}
if (lvl == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
maxLvlCall = std::max(maxLvlCall, lvl);
sortByLvl[lvl].push_back(z);
}
}
for (int z = 0; z < inDataProc.size(); ++z)
if (std::get<2>(inDataProc[z]) == -1)
sortByLvl[maxLvlCall + 1].push_back(z);
for (auto& byLvl : sortByLvl)
{
for (auto& idx : byLvl.second)
{
auto& tup = inDataProc[idx];
if (std::get<2>(tup) != -1)
{
__spf_print(1, " call inliner with [%s %s %d]\n", std::get<1>(tup).c_str(), std::get<0>(tup).c_str(), std::get<2>(tup));
bool isInlined = inliner(std::get<1>(tup), std::get<0>(tup), std::get<2>(tup), allFuncInfo, SPF_messages, newSymbsToDeclare, commonBlocks);
if (!isInlined)
{
__spf_print(1, " missing ...\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
}
}
}
else if (inDataChains.size())
{
setInlineAttributeToCalls(tmpM, inDataChains, hiddenData);
for (auto& startPoint : inDataChainsStart)
{
__spf_print(1, "call inliner from '%s'\n", startPoint.c_str());
inliner(startPoint, allFuncInfo, SPF_messages, newSymbsToDeclare, commonBlocks);
}
}
#endif
createDeclarations(newSymbsToDeclare, commonBlocks);
}