Files
SAPFOR/src/Utils/utils.cpp
2025-10-08 23:07:54 +03:00

1747 lines
51 KiB
C++

#include "leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <assert.h>
#include <locale>
#include <algorithm>
#include <thread>
#include "errors.h"
#include "utils.h"
#include "version.h"
#include "graph_loops.h"
#include "../Distribution/Array.h"
#include "../Distribution/Arrays.h"
#include "../DynamicAnalysis/gcov_info.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "json.hpp"
#if __SPF
#include "acc_analyzer.h"
#endif
using std::map;
using std::pair;
using std::tuple;
using std::set;
using std::vector;
using std::string;
using std::wstring;
using json = nlohmann::json;
#if __cplusplus >= 201703L
#include <filesystem>
namespace fs = std::filesystem;
#else
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/stat.h>
#endif
#endif
void createMapLoopGraph(map<int, LoopGraph*> &sortedLoopGraph, const vector<LoopGraph*> *loopGraph)
{
if (loopGraph)
{
for (int i = 0; i < (int)loopGraph->size(); ++i)
{
auto it = sortedLoopGraph.find((*loopGraph)[i]->lineNum);
if (it != sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
sortedLoopGraph[(*loopGraph)[i]->lineNum] = (*loopGraph)[i];
createMapLoopGraph(sortedLoopGraph, &((*loopGraph)[i]->children));
}
}
}
string FullNameWithExt(const char* filename)
{
char* basename = new char[strlen(filename) + 1];
int i;
strcpy(basename, filename);
for (i = (int)strlen(filename) - 1; i >= 0; --i)
{
if (basename[i] == '.')
{
basename[i] = '_';
break;
}
}
string retVal(basename);
delete[] basename;
return retVal;
}
string OnlyName(const char *filename)
{
char *basename = new char[strlen(filename) + 1];
int i;
strcpy(basename, filename);
for (i = (int)strlen(filename) - 1; i >= 0; --i)
{
if (basename[i] == '.')
{
basename[i] = '\0';
break;
}
}
string retVal(basename);
delete[] basename;
return retVal;
}
string OnlyExt(const char *filename)
{
char *extname = new char[1024];
extname[0] = '\0';
int i;
int len = (int)strlen(filename);
for (i = len - 1; i >= 0; --i)
{
if (filename[i] == '.')
{
i++;
int k;
int bound = len - i;
for (k = 0; k < bound; ++k, ++i)
extname[k] = filename[i];
extname[k] = '\0';
break;
}
}
string retVal(extname);
delete[] extname;
return retVal;
}
void printHelp(const char **passNames, const int lastPass)
{
printf("Help info for passes.\n\n");
printf(" -f90 free form\n");
printf(" -sh turn on static shadow analysis\n");
printf(" -shWidth maximum width of shadow in percent\n");
printf(" -ver/-Ver version of SAPFOR\n");
printf(" -priv turn on static private analysis\n");
printf(" -keep keep temporary files\n");
printf(" -keepSPF keep SPF directives\n");
printf(" -keepDVM keep DVM directives\n");
printf(" -allVars get all parallel versions\n");
printf(" -var N get specific parallel version, N=1,2,..\n");
printf(" -parse run parser with next option (-inl option allow to parse project for -inlineH/I regime)\n");
printf(" -pppa run performance statistic analyzer \n");
printf(" -fdvm run fdvm convertation\n");
printf(" -inlineH <funcName> run hierarchical inlining for all functions called from 'funcName'\n");
printf(" -inlineI <funcName> <lineNum> <fileName> run incremental inlining for function 'funcName' on 'lineNum' of 'fileName'\n");
printf(" -passInfo print passes information\n");
printf(" -dumpIR print IR information (works only with BUILD_IR pass)\n");
printf(" -ignoreDistArray ingnore array distribution information (set to all arrays no distribution state\n");
printf(" -shared shared memory and mpi programs parallelization\n");
printf(" -printSymbTable print all symbol tables of project\n");
printf("\n");
printf(" -F <folderName> output to folder\n");
printf(" -p <project name>\n");
printf(" -pass <pass_number>\n");
printf(" -passN <pass_name>\n");
for (int i = 0; i < lastPass; ++i)
printf(" pass_num = %d: %s\n", i, passNames[i]);
printf("\n");
printf(" -t <analysis_num>\n");
printf(" analysis_num = 13: insert parallel directives\n");
throw(-1);
}
void printVersion(const string pref)
{
printf("%sSAPFOR version is %s, build date: %s %s, c++ version %d\n", pref.c_str(), VERSION_SPF, __DATE__, __TIME__, __cplusplus);
}
extern bool noLogo;
extern int staticShadowAnalysis;
extern int keepDvmDirectives;
extern int ignoreIO;
extern int keepSpfDirs;
extern int maxShadowWidth;
const string printVersionAsFortranComm()
{
if (noLogo)
return "";
char buf[512];
sprintf(buf, "! *** generated by SAPFOR with version %s and build date: %s %s\n", VERSION_SPF, __DATE__, __TIME__);
string ret = buf;
ret += "! *** Enabled options ***:\n";
if (staticShadowAnalysis)
ret += "! *** shadow optimization\n";
if (keepDvmDirectives)
ret += "! *** consider DVMH directives\n";
if (keepSpfDirs)
ret += "! *** save SPF directives\n";
if (sharedMemoryParallelization)
ret += "! *** MPI program regime (shared memory parallelization)\n";
if (ignoreIO)
ret += "! *** ignore I/O checker for arrays (DVM I/O limitations)\n";
if (maxShadowWidth > 0)
ret += "! *** maximum shadow width is " + std::to_string(maxShadowWidth) + " percent\n";
ret += "! *** generated by SAPFOR\n";
return ret;
}
void convertToLower(string &str)
{
std::locale loc;
for (int i = 0; i < str.length(); ++i)
str[i] = std::tolower(str[i], loc);
}
void convertToUpper(string &str)
{
std::locale loc;
for (int i = 0; i < str.length(); ++i)
str[i] = std::toupper(str[i], loc);
}
void splitString(const string &strIn, const char delim, vector<string> &result, bool withQuotes)
{
std::stringstream ss;
ss.str(strIn);
vector<string> tmp_result;
string item;
while (std::getline(ss, item, delim))
tmp_result.push_back(item);
if (withQuotes)
{
bool quStarted = false;
item = "";
for (auto& elem : tmp_result)
{
if (elem.size())
{
if (quStarted)
{
item += " " + elem;
if (elem[elem.size() - 1] == '"')
{
quStarted = false;
result.push_back(item.erase(item.size() - 1, 1));
}
}
else
{
if (elem[0] == '"')
{
quStarted = true;
item = elem.erase(0, 1);
if (item[item.size() - 1] == '"')
{
quStarted = false;
result.push_back(item.erase(item.size() - 1, 1));
}
}
else
result.push_back(elem);
}
}
else if (quStarted)
item += " ";
}
}
else
result = tmp_result;
}
void splitString(const wstring& strIn, const char delim, vector<wstring>& result, bool withQuotes)
{
std::wstringstream ss;
ss.str(strIn);
vector<wstring> tmp_result;
wstring item;
wchar_t buf[1024];
while (ss.good())
{
ss.getline(buf, 1024, delim);
tmp_result.push_back(buf);
}
if (withQuotes)
{
bool quStarted = false;
item = L"";
for (auto& elem : tmp_result)
{
if (elem.size())
{
if (quStarted)
{
item += elem;
if (elem[elem.size() - 1] == L'"')
{
quStarted = false;
result.push_back(item.erase(item.size() - 1, 1));
}
}
else
{
if (elem[0] == '"')
{
quStarted = true;
item = elem.erase(0, 1);
if (item[item.size() - 1] == L'"')
{
quStarted = false;
result.push_back(item.erase(item.size() - 1, 1));
}
}
else
result.push_back(elem);
}
}
else if (quStarted)
item += L" ";
}
}
else
result = tmp_result;
}
void removeSubstrFromStr(string &str, const string &del)
{
string::size_type pos = str.find(del);
while (pos != string::npos)
{
str.erase(pos, del.size());
pos = str.find(del, pos + 1);
}
}
string convertFileName(const char *file)
{
string tmp(file);
std::reverse(tmp.begin(), tmp.end());
int t = 0;
while (tmp[t] != '\\' && tmp[t] != '/' && t < tmp.size())
t++;
tmp.erase(tmp.begin() + t, tmp.end());
std::reverse(tmp.begin(), tmp.end());
return tmp;
}
void printBlanks(const int sizeOfBlank, const int countOfBlanks)
{
for (int k = 0; k < countOfBlanks; ++k)
for (int m = 0; m < sizeOfBlank; ++m)
{
char buf[256];
sprintf(buf, " ");
addToGlobalBufferAndPrint(buf);
}
}
string globalOutputBuffer = "";
int consoleMode = 0;
void addToGlobalBufferAndPrint(const string &toPrint)
{
globalOutputBuffer += toPrint;
if (consoleMode)
{
printf("%s", toPrint.c_str());
fflush(NULL);
}
}
void clearGlobalBuffer() { globalOutputBuffer = ""; }
const string& getGlobalBuffer() { return globalOutputBuffer; }
set<short*> allocated;
extern map<string, vector<Messages>> SPF_messages; //file ->messages
void clearGlobalMessagesBuffer()
{
//clear allocated memory
for (auto& elem : allocated)
delete []elem;
allocated.clear();
SPF_messages.clear();
}
static map<string, vector<Messages>> removeCopies(map<string, vector<Messages>> in)
{
map<string, vector<Messages>> out;
for (auto& byFile : in)
{
map<tuple<typeMessage, int, int, wstring>, const Messages*> uniq;
for (auto& message : byFile.second)
{
auto key = message.getUniqKey();
/*string tmp = "";
for (auto& s : message.toString())
tmp += (char)s;
__spf_print(1, "%s\n", tmp.c_str());*/
uniq[key] = &message;
}
__spf_print(1, " messages filtering for file '%s': count before %d, count after %d\n", byFile.first.c_str(), byFile.second.size(), uniq.size());
vector<Messages> uniqV;
for (auto& elem : uniq)
{
/*string tmp = "";
for (auto& s : elem.second->toString())
tmp += (char)s;
__spf_print(1, "%s\n", tmp.c_str());*/
uniqV.push_back(*elem.second);
}
out[byFile.first] = uniqV;
}
return out;
}
static string convertGlobalMessagesBuffer()
{
auto copySPF_messages = removeCopies(SPF_messages);
for (auto &byFile : copySPF_messages)
{
vector<Messages> newVal;
bool waschanged = false;
for (auto &message : byFile.second)
{
if (message.getLine() > 0)
newVal.push_back(message);
else
waschanged = true;
}
if (waschanged)
byFile.second = newVal;
}
json allMessages = json::array();
for (auto& byFile : copySPF_messages)
{
json inFile;
inFile["file"] = byFile.first;
json array = json::array();
for (auto& message : byFile.second)
{
json msg = message.toJson();
array.push_back(msg);
}
inFile["messages"] = array;
allMessages.push_back(inFile);
}
json all;
all["allMessages"] = allMessages;
return all.dump();
}
void convertBuffers(string &resultM, string &result)
{
resultM = convertGlobalMessagesBuffer();
result = getGlobalBuffer();
}
bool isSPF_comment(const string &bufStr)
{
bool spfStart = false;
if (bufStr.size() > 6)
spfStart = (bufStr[0] == '!' || bufStr[0] == 'c') &&
bufStr[1] == '$' && bufStr[2] == 's' &&
bufStr[3] == 'p' && bufStr[4] == 'f';
return spfStart;
}
bool isDVM_comment(const string& bufStr)
{
bool dvmStart = false;
if (bufStr.size() > 6)
{
dvmStart = (bufStr[0] == '!' || bufStr[0] == 'c') &&
bufStr[1] == 'd' && bufStr[2] == 'v' &&
bufStr[3] == 'm' && bufStr[4] == '$';
}
return dvmStart;
}
static string renameExtension(const string& inc)
{
string ret = inc;
if (ret.find(".") != string::npos)
ret = OnlyName(ret.c_str());
ret += ".h";
return ret;
}
string renameInclude(const string& inc)
{
auto posStart = inc.find("'");
auto posEnd = inc.find("'", posStart + 1);
if (posStart == string::npos || posEnd == string::npos)
{
posStart = inc.find("\"");
posEnd = inc.find("\"", posStart + 1);
if (posStart == string::npos || posEnd == string::npos) {
__spf_print(1, "incorrect include string <%s>\n", inc.c_str());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
string substr = renameExtension(inc.substr(posStart + 1, posEnd - posStart - 1));
string ret = inc;
ret.replace(posStart + 1, posEnd - posStart - 1, substr);
return ret;
}
void copyIncludes(const set<string> &allIncludeFiles, const map<string, map<int, set<string>>> &commentsToInclude,
const map<string, map<int, set<string>>>& newCopyDeclToIncl,
const char *folderName, bool keepSpfDirs, bool isFreeStyle, bool isRename,
int removeDirs)
{
for (auto &include : allIncludeFiles)
{
if (commentsToInclude.find(include) != commentsToInclude.end())
continue;
string newCurrFile = string(folderName) + "/" + (isRename ? renameExtension(include) : include);
FILE *tryToOpen = fopen(newCurrFile.c_str(), "r");
if (tryToOpen == NULL)
{
__spf_print(1, " try to copy file '%s' to '%s'\n", include.c_str(), newCurrFile.c_str());
FILE *copyFile = fopen(newCurrFile.c_str(), "w");
FILE *oldFile = fopen(include.c_str(), "r");
if (!copyFile)
{
__spf_print(1, " can not open file '%s' for read\n", include.c_str());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
if (!oldFile)
{
__spf_print(1, " can not open file '%s' for write\n", newCurrFile.c_str());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
while (!feof(oldFile))
{
char buf[8192];
char *res = fgets(buf, 16384, oldFile);
if (res == NULL)
break;
const string orig(buf);
string bufStr(buf);
convertToLower(bufStr);
if (!keepSpfDirs)
{
bool spfStart = isSPF_comment(bufStr);
if (spfStart)
bufStr = "\n";
}
//remove DVM dirs or save DVM dirs as comment
if (removeDirs == 1 || removeDirs == 2)
{
if (bufStr[0] == '!' || bufStr[0] == 'c')
{
if (bufStr[1] == 'd' && bufStr[2] == 'v' && bufStr[3] == 'm' && bufStr[4] == '$')
{
if (removeDirs == 1)
bufStr = "";
else if (removeDirs == 2)
bufStr.insert(1, " ");
}
}
} //remove SPF dirs
else if (removeDirs == 3)
{
if (bufStr[0] == '!' || bufStr[0] == 'c')
if (bufStr[1] == '$' && bufStr[2] == 's' && bufStr[3] == 'p' && bufStr[4] == 'f')
bufStr = "";
}
// save original include name
if (bufStr.find("include") != string::npos)
fputs(orig.c_str(), copyFile);
else
{
if (bufStr != "")
fputs(bufStr.c_str(), copyFile);
}
}
auto newDecls = newCopyDeclToIncl.find(include);
if (newDecls != newCopyDeclToIncl.end())
for (auto& declByLine : newDecls->second)
for (auto& decl : declByLine.second)
fputs(decl.c_str(), copyFile);
fclose(oldFile);
fclose(copyFile);
//TODO: read options
/*string text = "";
copyFile = fopen(newCurrFile.c_str(), "r");
while (!feof(copyFile))
{
char buf[8192];
char* res = fgets(buf, 16384, copyFile);
if (res == NULL)
break;
text += res;
}
fclose(copyFile);
FileInfo tmp;
tmp.text = text;
tmp.style = isFreeStyle ? 2 : 0;
tmp.fileName = newCurrFile;
convertStyle(&tmp);*/
fflush(NULL);
}
else
fclose(tryToOpen);
}
}
string splitDirective(const string &in_)
{
if (in_ == "")
return "";
string in(in_);
string lastEnd = "";
if (in[in.size() - 1] == '\n')
{
in.erase(in.begin() + in_.size() - 1);
lastEnd = "\n";
}
string out = "";
if (in.size() < 71)
out = in;
else
{
char buf[72];
int len = in.size() - 71;
int idx = 71;
buf[in.copy(buf, 71, 0)] = '\0';
out += buf;
if (len > 0)
out += "\n!DVM$&";
while (len > 65)
{
buf[in.copy(buf, 65, idx)] = '\0';
out += buf;
len -= 65;
idx += 65;
if (len > 0)
out += "\n!DVM$&";
}
if (len > 0)
{
buf[in.copy(buf, 65, idx)] = '\0';
out += buf;
}
}
return out + lastEnd;
}
string splitDirectiveFull(const string &in_)
{
if (in_ == "")
return "";
string in(in_);
string lastEnd = "";
if (in[in.size() - 1] == '\n')
{
in.erase(in.begin() + in_.size() - 1);
lastEnd = "\n";
}
string out = "";
vector<string> splited;
splitString(in_, '\n', splited);
for (int z = 0; z < splited.size(); ++z)
{
if (z != 0)
out += "\n";
out += splitDirective(splited[z]);
}
return out + lastEnd;
}
void ExitFromOmegaTest(const int c) { throw c; }
extern "C" void ExitFromParser(const int c) { ExitFromOmegaTest(c); }
void sortFilesBySize(const char *proj_name)
{
FILE *proj = fopen(proj_name, "r");
if (proj)
{
map<pair<long, string>, string> files;
while (!feof(proj))
{
char buf[512];
fgets(buf, 512, proj);
string filename(buf);
long size;
FILE *fin = fopen(filename.c_str(), "rb");
FILE *p_fin = fin;
if (fin)
{
fseek(p_fin, 0, SEEK_END);
size = ftell(p_fin);
fclose(fin);
}
else
size = 0;
files[make_pair(size, filename)] = filename;
}
fclose(proj);
proj = fopen(proj_name, "w");
for (auto it = files.rbegin(); it != files.rend(); ++it)
fwrite(it->second.c_str(), sizeof(char), it->second.size(), proj);
fclose(proj);
}
else
{
__spf_print(1, "project file '%s' does not exist\n", proj_name);
throw(-1);
}
}
void uniteVectors(const vector<pair<pair<string, string>, vector<pair<int, int>>>> &first,
const vector<pair<pair<string, string>, vector<pair<int, int>>>> &second,
vector<pair<pair<string, string>, vector<pair<int, int>>>> &result)
{
int *uniteF = new int[first.size()];
int *uniteS = new int[second.size()];
memset(uniteF, 0, sizeof(int) * first.size());
memset(uniteS, 0, sizeof(int) * second.size());
for (int i = 0; i < (int)first.size(); ++i)
{
const string &arrayName = first[i].first.second;
int k;
for (k = 0; k < (int)second.size(); ++k)
{
if (uniteS[k] == 0)
{
if (arrayName == second[k].first.second)
{
uniteS[k] = 1;
break;
}
}
}
if (k != (int)second.size())
{
uniteF[i] = 1;
assert(first[i].second.size() == second[k].second.size());
result.push_back(make_pair(first[i].first, vector<pair<int, int>>(first[i].second.size())));
const vector<pair<int, int>> &boundsF = first[i].second;
const vector<pair<int, int>> &boundsS = second[k].second;
for (int z = 0; z < (int)boundsF.size(); ++z)
{
pair<int, int> newBounds = std::make_pair(std::max(boundsF[z].first, boundsS[z].first), std::max(boundsF[z].second, boundsS[z].second));
result.back().second[z] = newBounds;
}
}
}
for (int i = 0; i < (int)first.size(); ++i)
{
if (uniteF[i] == 0)
result.push_back(first[i]);
}
for (int i = 0; i < (int)second.size(); ++i)
{
if (uniteS[i] == 0)
result.push_back(second[i]);
}
delete[]uniteF;
delete[]uniteS;
}
#include <unordered_map>
#define FULL_ERROR_DUMP 1
// pointer -> type of alloc function
#if FULL_ERROR_DUMP
static std::unordered_map<void*, std::tuple<int, int, const char*>> pointerCollection;
static std::unordered_map<void*, std::tuple<int, int, const char*>> pointerCollectionLocal;
#else
static std::unordered_map<void*, std::tuple<int>> pointerCollection;
static std::unordered_map<void*, std::tuple<int>> pointerCollectionLocal;
#endif
static bool deleteInProgress = false;
static void* currentPointer = NULL;
static set<void*> deleted;
static bool storeInLocal = false;
// type == 0 -> free, type == 1 -> delete, type == 2 -> delete[]
// acc_analyzer.h: ControlFlowItem = 3, doLoopItem = 4, doLoops = 5, LabelCFI = 6, CLAStatementItem = 7
// VarItem = 8, VarSet = 9, DoLoopDataItem = 10, DoLoopDataList = 11
// CVarEntryInfo = 12, CScalarVarEntryInfo = 13, CRecordVarEntryInfo = 14
// ArraySubscriptData = 15, CArrayVarEntryInfo = 16, BasicBlockItem = 17,
// CallAnalysisLog = 18, CExprList = 19, SymbolKey = 20, CBasicBlock = 21
// CommonVarSet = 22, AnalysedCallsList = 23, CallData = 24, CommonVarInfo = 25
// CommonDataItem = 26, CommonData = 27, PrivateDelayedItem = 28, ActualDelayedData = 29
// ControlFlowGraph = 30
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type)
{
#if FULL_ERROR_DUMP
if (storeInLocal)
pointerCollectionLocal.insert(std::make_pair(pointer, std::make_tuple(type, line, file)));
pointerCollection.insert(std::make_pair(pointer, std::make_tuple(type, line, file)));
#else
if (storeInLocal)
pointerCollectionLocal.insert(std::make_pair(pointer, std::make_tuple(type)));
pointerCollection.insert(std::make_pair(pointer, std::make_tuple(type)));
#endif
}
extern "C" void removeFromCollection(void *pointer)
{
if (deleteInProgress)
{
if (pointer != currentPointer)
deleted.insert(pointer);
}
else
{
auto it = pointerCollection.find(pointer);
if (it != pointerCollection.end())
pointerCollection.erase(it);
if (storeInLocal)
{
auto it = pointerCollectionLocal.find(pointer);
if (it != pointerCollectionLocal.end())
pointerCollectionLocal.erase(it);
}
}
}
void startLocalColletion() { storeInLocal = true; }
void finishLocalColletion() { storeInLocal = false; }
void deleteLeaks()
{
map<string, int> places;
auto copy = pointerCollection;
for (auto& elem : copy)
{
string place = std::get<2>(elem.second);
places[place]++;
if (place.find("make_nodes.c") != string::npos)
{
free((char*)(elem.first));
auto it = pointerCollection.find(elem.first);
if (it != pointerCollection.end())
pointerCollection.erase(it);
}
}
}
void deletePointerAllocatedData(bool delLocal)
{
int leaks = 0;
int failed = 0;
deleteInProgress = true;
deleted.clear();
int maxS = -1;
int z = -1;
#if FULL_ERROR_DUMP
std::unordered_map<void*, std::tuple<int, int, const char*>>* toDelCollection = delLocal ? &pointerCollectionLocal : &pointerCollection;
#else
std::unordered_map<void*, std::tuple<int>>* toDelCollection = delLocal ? &pointerCollectionLocal : &pointerCollection;
#endif
for (auto &elem : *toDelCollection)
{
++z;
maxS = std::max(maxS, (int)deleted.size());
auto itD = deleted.find(elem.first);
if (deleted.find(elem.first) != deleted.end())
{
deleted.erase(itD);
continue;
}
const pair<void*, int> pointer = std::make_pair(elem.first, std::get<0>(elem.second));
currentPointer = pointer.first;
//printf("[%d]: %d %s\n", z, std::get<1>(elem.second), std::get<2>(elem.second));
//fflush(NULL);
if (pointer.second == 0)
{
if (pointer.first)
{
free((char*)(pointer.first));
leaks++;
}
else
failed++;
}
else if (pointer.second == 1)
{
if (pointer.first)
{
delete (char*)(pointer.first);
leaks++;
}
else
failed++;
}
else if (pointer.second == 2)
{
if (pointer.first)
{
delete [](char*)(pointer.first);
leaks++;
}
else
failed++;
}
else if (pointer.second >= 3 && pointer.second <= 30)
{
if (pointer.first)
{
switch (pointer.second)
{
#if __SPF
case 3: delete (ControlFlowItem*)pointer.first; break;
case 4: delete (doLoopItem*)pointer.first; break;
case 5: delete (doLoops*)pointer.first; break;
case 6: delete (LabelCFI*)pointer.first; break;
case 7: delete (CLAStatementItem*)pointer.first; break;
case 8: delete (VarItem*)pointer.first; break;
case 9: delete (VarSet*)pointer.first; break;
case 10: delete (DoLoopDataItem*)pointer.first; break;
case 11: delete (DoLoopDataList*)pointer.first; break;
case 12: delete (CVarEntryInfo*)pointer.first; break;
case 13: delete (CScalarVarEntryInfo*)pointer.first; break;
case 14: delete (CRecordVarEntryInfo*)pointer.first; break;
case 15: delete (ArraySubscriptData*)pointer.first; break;
case 16: delete (CArrayVarEntryInfo*)pointer.first; break;
case 17: delete (BasicBlockItem*)pointer.first; break;
case 18: delete (CallAnalysisLog*)pointer.first; break;
case 19: delete (CExprList*)pointer.first; break;
case 20: delete (SymbolKey*)pointer.first; break;
case 21: delete (CBasicBlock*)pointer.first; break;
case 22: delete (CommonVarSet*)pointer.first; break;
case 23: delete (AnalysedCallsList*)pointer.first; break;
case 24: delete (CallData*)pointer.first; break;
case 25: delete (CommonVarInfo*)pointer.first; break;
case 26: delete (CommonDataItem*)pointer.first; break;
case 27: delete (CommonData*)pointer.first; break;
case 28: delete (PrivateDelayedItem*)pointer.first; break;
case 29: delete (ActualDelayedData*)pointer.first; break;
case 30: delete (ControlFlowGraph*)pointer.first; break;
#endif
default:
break;
}
leaks++;
}
else
failed++;
}
}
if (leaks > 0)
printf("SAPFOR: detected %d leaks of memory\n", leaks);
if (failed > 0)
printf("SAPFOR: detected failed %d leaks of memory\n", failed);
printf("SAPFOR: deleted set size %d, maxS = %d\n", (int)deleted.size(), maxS);
toDelCollection->clear();
deleted.clear();
deleteInProgress = false;
currentPointer = NULL;
}
static unsigned arrayIdCounter = 0;
unsigned getUniqArrayId() { return arrayIdCounter++; }
static bool isAllRulesEqualWA_l(const vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> &rules)
{
if (rules.size() <= 1)
return true;
else
{
vector<tuple<DIST::Array*, int, pair<int, int>>> first = rules[0];
for (auto &elem : rules)
{
int z = 0;
if (elem.size() != first.size())
return false;
for (auto &item : elem)
if (std::get<2>(item) != std::get<2>(first[z++]))
return false;
}
return true;
}
}
template<typename T>
static bool isAllRulesEqual_l(T rules)
{
if (rules.size() <= 1)
return true;
else
{
for (auto &elem : rules)
if (elem != rules[0])
return false;
return true;
}
}
template<typename T>
static bool isAllRulesEqual_p(T rules)
{
if (rules.size() <= 1)
return true;
else
{
for (auto &elem : rules)
if (elem != rules[0])
return false;
return true;
}
}
bool isAllRulesEqualWithoutArray(const vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> &allRules)
{
return isAllRulesEqualWA_l(allRules);
}
bool isAllRulesEqual(const vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> &allRules)
{
return isAllRulesEqual_l(allRules);
}
bool isAllRulesEqual(const vector<vector<int>> &allRules)
{
return isAllRulesEqual_l(allRules);
}
bool isAllRulesEqual(const vector<vector<pair<int, int>>> &allRules)
{
return isAllRulesEqual_p(allRules);
}
static int newLineNumber = -2; // -1 is used for OMP
int getNextNegativeLineNumber()
{
int ret = newLineNumber;
newLineNumber--;
return ret;
}
void findAndReplaceDimentions(vector<tuple<DIST::Array*, int, pair<int, int>>> &rule, const DIST::Arrays<int> &allArrays)
{
for (int i = 0; i < rule.size(); ++i)
{
if (std::get<0>(rule[i]) == NULL)
continue;
int alignTo = -1;
int ok = allArrays.GetDimNumber(std::get<0>(rule[i]), (std::get<1>(rule[i])), alignTo);
if (ok != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
(std::get<1>(rule[i])) = alignTo;
}
}
vector<int> findLinksBetweenArrays(DIST::Array *from, DIST::Array *to, const uint64_t regionId, bool withCheck)
{
vector<int> retVal(from->GetDimSize());
std::fill(retVal.begin(), retVal.end(), -1);
if (to->IsTemplate())
{
if (to != from->GetTemplateArray(regionId, withCheck))
return retVal;
else
return from->GetLinksWithTemplate(regionId);
}
else
{
if (to->GetTemplateArray(regionId, withCheck) != from->GetTemplateArray(regionId, withCheck))
{
string leftT = to->GetTemplateArray(regionId, withCheck) ? to->GetTemplateArray(regionId, withCheck)->GetShortName() : "nul";
string rightT = from->GetTemplateArray(regionId, withCheck) ? from->GetTemplateArray(regionId, withCheck)->GetShortName() : "nul";
__spf_print(1, "regionId = %lld: templates for array %s and %s not eq: %s != %s\n",
regionId, from->GetName().c_str(), to->GetName().c_str(), leftT.c_str(), rightT.c_str());
}
else
{
auto ruleL = from->GetLinksWithTemplate(regionId);
auto ruleR = to->GetLinksWithTemplate(regionId);
int currD = 0;
for (auto &elem1 : ruleL)
{
int idx = 0;
for (auto &elem2 : ruleR)
{
if (elem2 == elem1)
{
retVal[currD] = idx;
break;
}
++idx;
}
++currD;
}
}
return retVal;
}
}
std::wstring to_wstring(const std::string str) { return std::wstring(str.begin(), str.end()); }
template<typename objT>
objT& getObjectForFileFromMap(const char *fileName, map<string, objT> &mapObject)
{
auto it = mapObject.find(fileName);
if (it == mapObject.end())
it = mapObject.insert(it, std::make_pair(fileName, objT()));
return it->second;
}
template vector<int>& getObjectForFileFromMap(const char* fileName, map<string, vector<int>>&);
template vector<Messages>& getObjectForFileFromMap(const char *fileName, map<string, vector<Messages>>&);
template vector<LoopGraph*>& getObjectForFileFromMap(const char *fileName, map<string, vector<LoopGraph*>>&);
template vector<FuncInfo*>& getObjectForFileFromMap(const char *fileName, map<string, vector<FuncInfo*>>&);
template map<int, Gcov_info>& getObjectForFileFromMap(const char *fileName, map<string, map<int, Gcov_info>>&);
template map<int, double>& getObjectForFileFromMap(const char *fileName, map<string, map<int, double>>&);
#if __SPF
template map<SgStatement*, vector<SgStatement*>>& getObjectForFileFromMap(const char* fileName, map<string, map<SgStatement*, vector<SgStatement*>>>&);
#endif
static set<string> mpiFunctions;
bool isMpiFunction(const string& func)
{
if (mpiFunctions.size() == 0)
{
mpiFunctions.insert("mpi_abort");
mpiFunctions.insert("mpi_address");
mpiFunctions.insert("mpi_allgather");
mpiFunctions.insert("mpi_allgatherv");
mpiFunctions.insert("mpi_allreduce");
mpiFunctions.insert("mpi_alltoall");
mpiFunctions.insert("mpi_alltoallv");
mpiFunctions.insert("mpi_barrier");
mpiFunctions.insert("mpi_bcast");
mpiFunctions.insert("mpi_bsend");
mpiFunctions.insert("mpi_bsend_init");
mpiFunctions.insert("mpi_buffer_attach");
mpiFunctions.insert("mpi_buffer_detach");
mpiFunctions.insert("mpi_cart_coords");
mpiFunctions.insert("mpi_cart_create");
mpiFunctions.insert("mpi_cart_get");
mpiFunctions.insert("mpi_cart_rank");
mpiFunctions.insert("mpi_cart_shift");
mpiFunctions.insert("mpi_cart_sub");
mpiFunctions.insert("mpi_cartdim_get");
mpiFunctions.insert("mpi_comm_create");
mpiFunctions.insert("mpi_comm_dup");
mpiFunctions.insert("mpi_comm_free");
mpiFunctions.insert("mpi_comm_group");
mpiFunctions.insert("mpi_comm_rank");
mpiFunctions.insert("mpi_comm_size");
mpiFunctions.insert("mpi_comm_split");
mpiFunctions.insert("mpi_dims_create");
mpiFunctions.insert("mpi_finalize");
mpiFunctions.insert("mpi_gather");
mpiFunctions.insert("mpi_gatherv");
mpiFunctions.insert("mpi_get_count");
mpiFunctions.insert("mpi_get_processor_name");
mpiFunctions.insert("mpi_graph_create");
mpiFunctions.insert("mpi_graph_get");
mpiFunctions.insert("mpi_graph_neighbors");
mpiFunctions.insert("mpi_graph_neighbors_count");
mpiFunctions.insert("mpi_graphdims_get");
mpiFunctions.insert("mpi_group_compare");
mpiFunctions.insert("mpi_group_difference");
mpiFunctions.insert("mpi_group_excl");
mpiFunctions.insert("mpi_group_free");
mpiFunctions.insert("mpi_group_incl");
mpiFunctions.insert("mpi_group_intersection");
mpiFunctions.insert("mpi_group_rank");
mpiFunctions.insert("mpi_group_size");
mpiFunctions.insert("mpi_group_translate_ranks");
mpiFunctions.insert("mpi_group_union");
mpiFunctions.insert("mpi_ibsend");
mpiFunctions.insert("mpi_init");
mpiFunctions.insert("mpi_initialized");
mpiFunctions.insert("mpi_iprobe");
mpiFunctions.insert("mpi_irecv");
mpiFunctions.insert("mpi_irsend");
mpiFunctions.insert("mpi_isend");
mpiFunctions.insert("mpi_issend");
mpiFunctions.insert("mpi_op_create");
mpiFunctions.insert("mpi_op_free");
mpiFunctions.insert("mpi_pack");
mpiFunctions.insert("mpi_pack_size");
mpiFunctions.insert("mpi_probe");
mpiFunctions.insert("mpi_recv");
mpiFunctions.insert("mpi_recv_init");
mpiFunctions.insert("mpi_reduce");
mpiFunctions.insert("mpi_reduce_scatter");
mpiFunctions.insert("mpi_request_free");
mpiFunctions.insert("mpi_rsend");
mpiFunctions.insert("mpi_rsend_init");
mpiFunctions.insert("mpi_scan");
mpiFunctions.insert("mpi_scatter");
mpiFunctions.insert("mpi_scatterv");
mpiFunctions.insert("mpi_send");
mpiFunctions.insert("mpi_send_init");
mpiFunctions.insert("mpi_sendrecv");
mpiFunctions.insert("mpi_sendrecv_replace");
mpiFunctions.insert("mpi_ssend");
mpiFunctions.insert("mpi_ssend_init");
mpiFunctions.insert("mpi_start");
mpiFunctions.insert("mpi_startall");
mpiFunctions.insert("mpi_test");
mpiFunctions.insert("mpi_testall");
mpiFunctions.insert("mpi_testany");
mpiFunctions.insert("mpi_testsome");
mpiFunctions.insert("mpi_topo_test");
mpiFunctions.insert("mpi_type_commit");
mpiFunctions.insert("mpi_type_contiguous");
mpiFunctions.insert("mpi_type_extent");
mpiFunctions.insert("mpi_type_free");
mpiFunctions.insert("mpi_type_hindexed");
mpiFunctions.insert("mpi_type_hvector");
mpiFunctions.insert("mpi_type_indexed");
mpiFunctions.insert("mpi_type_lb");
mpiFunctions.insert("mpi_type_size");
mpiFunctions.insert("mpi_type_struct");
mpiFunctions.insert("mpi_type_ub");
mpiFunctions.insert("mpi_type_vector");
mpiFunctions.insert("mpi_unpack");
mpiFunctions.insert("mpi_wait");
mpiFunctions.insert("mpi_waitall");
mpiFunctions.insert("mpi_waitany");
mpiFunctions.insert("mpi_waitsome");
mpiFunctions.insert("mpi_wtick");
mpiFunctions.insert("mpi_wtime");
}
return mpiFunctions.find(func) != mpiFunctions.end();
}
map<DIST::Array*, DIST::ArrayAccessInfo*> createMapOfArrayAccess(const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays)
{
map<DIST::Array*, DIST::ArrayAccessInfo*> out;
for (auto& elem : declaredArrays)
out[elem.second.first] = elem.second.second;
return out;
}
string readFileToStr(const string& name)
{
string sf;
std::ifstream inf;
inf.open(name);
if (!inf)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
getline(inf, sf, '\0');
inf.close();
return sf;
}
void writeFileFromStr(const string& name, const string &data)
{
string sf;
std::ofstream outf;
outf.open(name);
if (!outf)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
outf << data;
outf.close();
}
ParallelRegion* getRegionById(const vector<ParallelRegion*>& regions, const uint64_t regionId)
{
for (auto& region : regions)
if (region->GetId() == regionId)
return region;
return NULL;
}
ParallelRegion* getRegionByName(const vector<ParallelRegion*>& regions, const string& regionName)
{
string test = regionName;
convertToLower(test);
for (auto& region : regions)
if (region->GetName() == test)
return region;
return NULL;
}
ParallelRegion* getRegionByLine(const vector<ParallelRegion*>& regions, const string& file, const int line)
{
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
return regions[0];
else if (regions.size() > 0)
{
set<ParallelRegion*> regFound;
for (int i = 0; i < regions.size(); ++i)
if (regions[i]->HasThisLine(line, file))
regFound.insert(regions[i]);
if (regFound.size() == 0)
return NULL;
else if (regFound.size() == 1)
return *regFound.begin();
else
{
__spf_print(1, "WARN: this lines included in more than one region!!\n");
return NULL;
}
}
else
return NULL;
return NULL;
}
std::pair<ParallelRegion*, const ParallelRegionLines*> getRegionAndLinesByLine(const vector<ParallelRegion*>& regions, const string& file, const int line)
{
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
return { regions[0], NULL };
else if (regions.size() > 0)
{
map<ParallelRegion*, const ParallelRegionLines*> regFound;
const ParallelRegionLines* foundLines = NULL;
for (int i = 0; i < regions.size(); ++i)
if (regions[i]->HasThisLine(line, file, &foundLines))
regFound[regions[i]] = foundLines;
if (regFound.size() == 0)
return { NULL, NULL };
else if (regFound.size() == 1)
return *regFound.begin();
else
{
__spf_print(1, "WARN: this lines included in more than one region!!\n");
return { NULL, NULL };
}
}
else
return { NULL, NULL };
return { NULL, NULL };
}
set<ParallelRegion*> getAllRegionsByLine(const vector<ParallelRegion*>& regions, const string& file, const int line)
{
set<ParallelRegion*> regFound;
if (regions.size() == 1 && regions[0]->GetName() == "DEFAULT") // only default
regFound.insert(regions[0]);
else if (regions.size() > 0)
{
for (int i = 0; i < regions.size(); ++i)
if (regions[i]->HasThisLine(line, file))
regFound.insert(regions[i]);
}
return regFound;
}
static bool checkFormat(const string& toCheck, const string& given)
{
if (given == "" || given == "*")
{
if (toCheck == "for" || toCheck == "f90" || toCheck == "fdv" ||
toCheck == "ftn" || toCheck == "f95" || toCheck == "f03" ||
toCheck == "f")
{
return true;
}
}
else if (toCheck == given)
return true;
return false;
}
pair<vector<string>, vector<string>> splitCommandLineForParse(char** argv, int argc, bool& isInline)
{
#if __cplusplus >= 201703L
vector<fs::path> filesInDir;
for (const auto& entry : fs::directory_iterator(fs::current_path()))
filesInDir.push_back(entry.path().filename());
#endif
vector<string> options;
set<string> files;
//fdv|f|ftn|for|f90|f95|f03
for (int z = 0; z < argc; ++z)
{
string arg = argv[z];
string ext = OnlyExt(arg.c_str());
convertToLower(ext);
if (arg.find("*") != string::npos || checkFormat(ext, ""))
{
if (arg.find("*") == string::npos)
{
if (checkFormat(ext, ""))
files.insert(arg);
else
printf("skip file %s\n", arg.c_str());
}
else
{
#if __cplusplus >= 201703L
for (auto& file : filesInDir)
{
auto cmp_ext = file.extension().string();
convertToLower(cmp_ext);
if (cmp_ext.size() && cmp_ext[0] == '.')
cmp_ext.erase(cmp_ext.begin());
if (checkFormat(cmp_ext, ext))
files.insert(file.filename().string());
}
#endif
}
}
else
{
if (arg == "-inl")
isInline = true;
else if (arg.find("-") != string::npos)
options.push_back(arg);
else
printf(" skip option %s\n", arg.c_str());
}
}
vector<string> filesV;
for (auto& elem : files)
{
FILE* check = fopen(elem.c_str(), "r");
if (check)
{
filesV.push_back(elem);
printf(" parse file '%s'\n", elem.c_str());
fclose(check);
}
else
printf(" skip not existing file '%s'\n", elem.c_str());
}
printf(" options: ");
for (auto& opt : options)
printf("%s ", opt.c_str());
printf("\n");
return make_pair(options, filesV);
}
bool createDirectory(const string& name)
{
#if __cplusplus >= 201703L
if (fs::exists(name))
return true;
else
return fs::create_directories(name);
#else
#ifdef _WIN32
if (_mkdir(name.c_str()) == 0)
return true;
#else
if (mkdir(name.c_str(), 0777) == 0)
return true;
#endif
return false;
#endif
}
string getClearName(const string& in)
{
char fromChar;
if (in.find('.') == string::npos)
{
if (in.find("::") == string::npos)
return in;
else
fromChar = ':';
}
else
fromChar = '.';
string ret = in;
auto it = ret.rfind(fromChar);
if (it == string::npos)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
ret = ret.substr(it + 1);
return ret;
}
wstring fixedLongFormat(const wchar_t* old_)
{
/*#if __SPF
return old_ ? old_ : L"";
#endif*/
if (old_ == NULL)
return L"";
wstring old(old_);
//exclude russian codes
if (old_[0] == L'R' && (old_[1] == L'R' || (old_[1] >= L'0' && old_[1] <= L'9')))
return old;
wstring ret = L"";
for (int z = 0; z < old.size(); ++z)
{
if (old[z] == L'%')
{
if (z + 1 < old.size())
{
if (old[z + 1] == L's')
{
ret += L"%ls";
z++;
continue;
}
}
}
ret += old[z];
}
return ret;
}
const set<string> getExcludedModules() { return { "omp_lib", "ifport" }; };
map<string, DIST::Array*> sortArraysByName(const set<DIST::Array*>& toSort)
{
map<string, DIST::Array*> sorted;
for (auto& array : toSort)
sorted[array->GetName()] = array;
if (sorted.size() != toSort.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return sorted;
}
vector<string> splitAndArgvCreate(const string& options)
{
vector<string> optSplited;
optSplited.push_back("");
splitString(options, ' ', optSplited, true);
vector<string> optSplited1;
for (auto& elem : optSplited)
if (elem != "")
optSplited1.push_back(elem);
optSplited1.insert(optSplited1.begin(), "");
for (int z = 0; z < optSplited1.size(); ++z)
{
//printf("%s\n", optSplited1[z].c_str());
if (optSplited1[z][0] == '"' && optSplited1[z][optSplited1[z].size() - 1] == '"')
optSplited1[z] = optSplited1[z].substr(1, optSplited1[z].size() - 2);
}
return optSplited1;
}
static bool isNotNullIntersection(const set<DIST::Array*>& first, const set<DIST::Array*>& second)
{
for (auto& elem1 : first)
if (second.find(elem1) != second.end())
return true;
return false;
}
set<DIST::Array*> fillDistributedArraysD(const DataDirective& dataDirectives,
const map<DIST::Array*, tuple<int, string, string>>& tableOfUniqNamesByArray,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
bool onlyCommon)
{
set<DIST::Array*> distrArrays;
set<DIST::Array*> distrArraysD;
set<DIST::Array*> distrArraysAdded;
for (int z = 0; z < dataDirectives.distrRules.size(); ++z)
distrArraysD.insert(dataDirectives.distrRules[z].first);
for (int z = 0; z < dataDirectives.alignRules.size(); ++z)
distrArraysD.insert(dataDirectives.alignRules[z].alignArray);
for (auto& elem : tableOfUniqNamesByArray)
{
set<DIST::Array*> realRefs;
getRealArrayRefs(elem.first, elem.first, realRefs, arrayLinksByFuncCalls);
if (isNotNullIntersection(realRefs, distrArraysD))
distrArraysAdded.insert(elem.first);
}
for (auto& elem : distrArraysD)
{
if (onlyCommon)
{
if (elem->GetLocation().first == DIST::l_COMMON)
distrArrays.insert(elem);
}
else
distrArrays.insert(elem);
}
for (auto& elem : distrArraysAdded)
{
if (onlyCommon)
{
if (elem->GetLocation().first == DIST::l_COMMON)
distrArrays.insert(elem);
}
else
distrArrays.insert(elem);
}
return distrArrays;
}
set<string> fillDistributedArrays(const DataDirective& dataDirectives,
const map<DIST::Array*, tuple<int, string, string>>& tableOfUniqNamesByArray,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
bool onlyCommon, bool shortName)
{
set<string> distrArrays;
set<DIST::Array*> ret = fillDistributedArraysD(dataDirectives, tableOfUniqNamesByArray, arrayLinksByFuncCalls, onlyCommon);
for (auto& elem : ret)
distrArrays.insert(shortName ? elem->GetShortName() : elem->GetName());
return distrArrays;
}
void copyStringToShort(short*& result, const string& resVal, bool withEnd)
{
result = new short[resVal.size() + 1];
allocated.insert(result);
for (int i = 0; i < resVal.size(); ++i)
result[i] = resVal[i];
if (withEnd)
result[resVal.size()] = (short)'\0';
}
void dumpMessages(bool inCatch, const map<string, vector<Messages>>& messages, const char *vis_path)
{
json byFileArray = json::array();
for (auto& byFile : messages)
{
json inFile;
inFile["file"] = byFile.first;
json messages = json::array();
for (auto& message : byFile.second)
{
if (inCatch)
message.print(byFile.first);
messages.push_back(message.toJson());
}
inFile["messages"] = messages;
byFileArray.push_back(inFile);
}
json allMessages;
allMessages["allMessages"] = byFileArray;
const string dump = allMessages.dump().c_str();
if (dump.size())
{
FILE* outF = fopen((string(vis_path) + "/error_messages.json").c_str(), "w");
if (outF)
{
fprintf(outF, "%s", dump.c_str());
fclose(outF);
}
}
}