2025-06-02 19:08:09 +03:00
|
|
|
#include "leak_detector.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <tuple>
|
|
|
|
|
|
|
|
|
|
#include "dvm.h"
|
|
|
|
|
#include "../Utils/errors.h"
|
|
|
|
|
#include "../Utils/SgUtils.h"
|
|
|
|
|
|
|
|
|
|
#include "uniq_call_chain_dup.h"
|
2025-06-02 19:08:09 +03:00
|
|
|
#include "graph_calls.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
#include "../GraphCall/graph_calls_func.h"
|
2025-06-02 19:08:09 +03:00
|
|
|
#include "expr_transform.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
#include "../VerificationCode/verifications.h"
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
struct callVars
|
|
|
|
|
{
|
|
|
|
|
callVars() { }
|
|
|
|
|
callVars(const pair<void*, int>& place, const vector<void*>& var, void* parentSt) : callVariant(var)
|
|
|
|
|
{
|
|
|
|
|
callPlaces.push_back(make_tuple(place.first, place.second, parentSt));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<tuple<void*, int, void*>> callPlaces;
|
|
|
|
|
vector<void*> callVariant;
|
|
|
|
|
string copiedName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct callInfo
|
|
|
|
|
{
|
|
|
|
|
callInfo() { countCalls = 0; }
|
|
|
|
|
|
|
|
|
|
int countCalls;
|
|
|
|
|
vector<callVars> variantCall;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bool checkUniqAndAdd(vector<callVars> &vars, const vector<void*> ¤t, const pair<void*, int> &callPlace, void* parentSt)
|
|
|
|
|
{
|
|
|
|
|
for (auto& elem : vars)
|
|
|
|
|
{
|
|
|
|
|
if (elem.callVariant == current)
|
|
|
|
|
{
|
|
|
|
|
elem.callPlaces.push_back(make_tuple(callPlace.first, callPlace.second, parentSt));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vars.push_back(callVars(callPlace, current, parentSt));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static vector<void*> createParamCalls(const pair<void*, int> &callPointer, const string &fileN)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(fileN) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgExpression *callList = NULL;
|
|
|
|
|
if (callPointer.second == PROC_STAT)
|
|
|
|
|
callList = ((SgStatement*)callPointer.first)->expr(0);
|
|
|
|
|
else if (callPointer.second == FUNC_CALL)
|
|
|
|
|
callList = ((SgExpression*)callPointer.first)->lhs();
|
|
|
|
|
else
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
vector<void*> packCall;
|
|
|
|
|
|
|
|
|
|
while (callList)
|
|
|
|
|
{
|
|
|
|
|
auto curr = callList->lhs();
|
|
|
|
|
if (curr->variant() == ARRAY_REF)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* par = OriginalSymbol(callList->lhs()->symbol());
|
|
|
|
|
DIST::Array* array = getArrayFromDeclarated(declaratedInStmt(par), par->identifier());
|
|
|
|
|
if (array)
|
|
|
|
|
{
|
|
|
|
|
if (array->IsNotDistribute() == false)
|
|
|
|
|
packCall.push_back(array);
|
|
|
|
|
else
|
|
|
|
|
packCall.push_back(NULL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
packCall.push_back(NULL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
packCall.push_back(NULL);
|
|
|
|
|
callList = callList->rhs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return packCall;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<FuncInfo*, callInfo> countOfCalls(const map<string, vector<FuncInfo*>> &allFuncs, const map<string, FuncInfo*> &mapOfFunc)
|
|
|
|
|
{
|
|
|
|
|
map<FuncInfo*, int> count;
|
|
|
|
|
map<FuncInfo*, vector<callVars>> variantCall;
|
|
|
|
|
|
|
|
|
|
for (auto& fromFile : allFuncs)
|
|
|
|
|
{
|
|
|
|
|
for (auto& elem : fromFile.second)
|
|
|
|
|
{
|
|
|
|
|
count[elem] = 0;
|
|
|
|
|
variantCall[elem] = vector<callVars>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& fromFile : allFuncs)
|
|
|
|
|
{
|
|
|
|
|
for (auto& elem : fromFile.second)
|
|
|
|
|
{
|
|
|
|
|
int p = 0;
|
2023-11-05 13:08:57 +03:00
|
|
|
for (auto& callInfo : elem->callsFromDetailed)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-05 13:08:57 +03:00
|
|
|
auto& detailed = callInfo.detailCallsFrom;
|
2023-09-14 19:43:13 +03:00
|
|
|
auto it = mapOfFunc.find(detailed.first);
|
|
|
|
|
if (it != mapOfFunc.end())
|
|
|
|
|
{
|
|
|
|
|
auto var = variantCall.find(it->second);
|
2023-11-05 13:08:57 +03:00
|
|
|
auto createPackCall = createParamCalls(elem->callsFromDetailed[p].pointerDetailCallsFrom, elem->fileName);
|
2023-09-14 19:43:13 +03:00
|
|
|
|
2023-11-05 13:08:57 +03:00
|
|
|
if (checkUniqAndAdd(var->second, createPackCall, elem->callsFromDetailed[p].pointerDetailCallsFrom, elem->callsFromDetailed[p].parentForPointer))
|
2023-09-14 19:43:13 +03:00
|
|
|
count[it->second]++;
|
|
|
|
|
}
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, callInfo> retInfo;
|
|
|
|
|
for (auto& elem : count)
|
|
|
|
|
retInfo[elem.first].countCalls = elem.second;
|
|
|
|
|
for (auto& elem : variantCall)
|
|
|
|
|
retInfo[elem.first].variantCall = elem.second;
|
|
|
|
|
return retInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int getRealCallCount(const callInfo &info, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCall)
|
|
|
|
|
{
|
|
|
|
|
if (info.variantCall.size() > 1)
|
|
|
|
|
return info.countCalls;
|
|
|
|
|
else if (info.variantCall.size() == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const callVars& var = info.variantCall[0];
|
|
|
|
|
for (int z = 0; z < var.callVariant.size(); ++z)
|
|
|
|
|
{
|
|
|
|
|
if (var.callVariant[z])
|
|
|
|
|
{
|
|
|
|
|
DIST::Array* ref = (DIST::Array*)var.callVariant[z];
|
|
|
|
|
set<DIST::Array*> realRefs;
|
|
|
|
|
getRealArrayRefs(ref, ref, realRefs, arrayLinksByFuncCall);
|
|
|
|
|
if (realRefs.size() > 1)
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static vector<FuncInfo*> detect(const map<string, vector<FuncInfo*>> &allFuncs, const map<string, FuncInfo*> &mapOfFunc,
|
|
|
|
|
map<FuncInfo*, callInfo> &funcInfoOfCall, const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCall)
|
|
|
|
|
{
|
|
|
|
|
vector<FuncInfo*> retVal;
|
|
|
|
|
funcInfoOfCall = countOfCalls(allFuncs, mapOfFunc);
|
|
|
|
|
|
|
|
|
|
for (auto &fromFile : allFuncs)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(fromFile.first) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto &elem : fromFile.second)
|
|
|
|
|
{
|
|
|
|
|
SgProgHedrStmt *prog = isSgProgHedrStmt(elem->funcPointer->GetOriginal());
|
|
|
|
|
checkNull(prog, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
if (prog->variant() == PROG_HEDR)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (getRealCallCount(funcInfoOfCall[elem], arrayLinksByFuncCall) <= 1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (int z = 0; z < prog->numberOfParameters(); ++z)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol *par = OriginalSymbol(prog->parameter(z));
|
|
|
|
|
DIST::Array *array = getArrayFromDeclarated(declaratedInStmt(par), par->identifier());
|
|
|
|
|
|
|
|
|
|
if (array)
|
|
|
|
|
{
|
|
|
|
|
if (array->IsNotDistribute() == false)
|
|
|
|
|
{
|
|
|
|
|
retVal.push_back(elem);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static set<FuncInfo*> getFullCallsFrom(FuncInfo *from, const map<string, FuncInfo*> &mapOfFunc)
|
|
|
|
|
{
|
|
|
|
|
set<FuncInfo*> callsFromFull;
|
|
|
|
|
callsFromFull.insert(from);
|
|
|
|
|
|
|
|
|
|
bool change = true;
|
|
|
|
|
while (change)
|
|
|
|
|
{
|
|
|
|
|
change = false;
|
|
|
|
|
set<FuncInfo*> newAdd;
|
|
|
|
|
for (auto& func: callsFromFull)
|
|
|
|
|
{
|
|
|
|
|
for (auto& elem : func->callsFrom)
|
|
|
|
|
{
|
|
|
|
|
auto it = mapOfFunc.find(elem);
|
|
|
|
|
if (it != mapOfFunc.end())
|
|
|
|
|
{
|
|
|
|
|
auto it2 = callsFromFull.find(it->second);
|
|
|
|
|
if (callsFromFull.end() == it2)
|
|
|
|
|
{
|
|
|
|
|
newAdd.insert(it->second);
|
|
|
|
|
change = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& elem : newAdd)
|
|
|
|
|
callsFromFull.insert(elem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callsFromFull;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isAllDone(const vector<bool>& done)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& elem : done)
|
|
|
|
|
if (elem == false)
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<FuncInfo*, set<FuncInfo*>> groupByMainCall(const vector<FuncInfo*> &toCopy, const map<string, FuncInfo*> &mapOfFunc)
|
|
|
|
|
{
|
|
|
|
|
set<FuncInfo*> copySet(toCopy.begin(), toCopy.end());
|
|
|
|
|
|
|
|
|
|
vector<bool> done(toCopy.size());
|
|
|
|
|
std::fill(done.begin(), done.end(), false);
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> groups;
|
|
|
|
|
|
|
|
|
|
while (!isAllDone(done))
|
|
|
|
|
{
|
|
|
|
|
int z = 0;
|
|
|
|
|
for (; z < done.size(); ++z)
|
|
|
|
|
{
|
|
|
|
|
if (!done[z])
|
|
|
|
|
{
|
|
|
|
|
for (auto& callsTo : toCopy[z]->callsTo)
|
|
|
|
|
{
|
|
|
|
|
if (copySet.find(callsTo) != copySet.end())
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
done[z] = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (z == done.size() + 1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
groups[toCopy[z]] = set<FuncInfo*>();
|
|
|
|
|
|
|
|
|
|
set<FuncInfo*> fullCalls = getFullCallsFrom(toCopy[z], mapOfFunc);
|
|
|
|
|
for (int p = 0; p < done.size(); ++p)
|
|
|
|
|
{
|
|
|
|
|
//self
|
|
|
|
|
if (p == z)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (fullCalls.find(toCopy[p]) != fullCalls.end())
|
|
|
|
|
{
|
|
|
|
|
groups[toCopy[z]].insert(toCopy[p]);
|
|
|
|
|
done[p] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return groups;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void fillOrigCopyEx(SgExpression *orig, SgExpression *copy, map<SgExpression*, SgExpression*> &origCopyEx)
|
|
|
|
|
{
|
|
|
|
|
if (orig)
|
|
|
|
|
{
|
|
|
|
|
origCopyEx[orig] = copy;
|
|
|
|
|
|
|
|
|
|
fillOrigCopyEx(orig->lhs(), copy->lhs(), origCopyEx);
|
|
|
|
|
fillOrigCopyEx(orig->rhs(), copy->rhs(), origCopyEx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void findAllFunctionCalls(SgExpression* ex, const vector<void*> ¶mVar,
|
|
|
|
|
const string& file, set<SgExpression*>& toChange)
|
|
|
|
|
{
|
|
|
|
|
if (ex)
|
|
|
|
|
{
|
|
|
|
|
if (ex->variant() == FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
pair<void*, int> callPointer = make_pair(ex, FUNC_CALL);
|
|
|
|
|
if (createParamCalls(callPointer, file) == paramVar)
|
|
|
|
|
toChange.insert(ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ex->lhs())
|
|
|
|
|
findAllFunctionCalls(ex->lhs(), paramVar, file, toChange);
|
|
|
|
|
if (ex->rhs())
|
|
|
|
|
findAllFunctionCalls(ex->rhs(), paramVar, file, toChange);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void findDeclAndDuplicate(SgStatement* func, const string& funcName, const string& funcNameCopy, int variant)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(func->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
if (variant != FUNC_HEDR)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SgStatement* end = func->lastNodeOfStmt();
|
|
|
|
|
bool hasImplicit = false;
|
|
|
|
|
for (auto st = func; st != end; st = st ->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (isSgExecutableStatement(st))
|
|
|
|
|
break;
|
|
|
|
|
if (st->variant() == IMPL_DECL)
|
|
|
|
|
{
|
|
|
|
|
hasImplicit = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasImplicit)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (auto st = func; st != end; st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (isSgExecutableStatement(st))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* ex = st->expr(0);
|
|
|
|
|
while (ex)
|
|
|
|
|
{
|
|
|
|
|
auto s = ex->lhs()->symbol();
|
|
|
|
|
if (s && s->identifier() == funcName)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* copy = ex->lhs()->copyPtr();
|
|
|
|
|
copy->setSymbol(s->copy());
|
|
|
|
|
copy->symbol()->changeName(funcNameCopy.c_str());
|
|
|
|
|
SgExpression* next = ex->rhs();
|
|
|
|
|
|
|
|
|
|
ex->setRhs(new SgExpression(ex->variant(), copy, next));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ex = ex->rhs();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void findInterfaceBlockAndDuplicate(SgStatement* func, const string& ifaceName, const string& ifaceCopy, int variant)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(func->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgStatement* end = func->lastNodeOfStmt();
|
|
|
|
|
for ( ; func != end; func = func->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (func->variant() == INTERFACE_STMT)
|
|
|
|
|
{
|
|
|
|
|
SgStatement* ifaceEnd = func->lastNodeOfStmt();
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (auto st = func->lexNext(); st != ifaceEnd; st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == variant && st->symbol()->identifier() == ifaceName)
|
|
|
|
|
{
|
|
|
|
|
auto copy = st->copyBlockPtr();
|
|
|
|
|
st->insertStmtBefore(*copy, *st->controlParent());
|
|
|
|
|
SgSymbol* copyS = ©->symbol()->copy();
|
|
|
|
|
copyS->changeName(ifaceCopy.c_str());
|
|
|
|
|
copy->setSymbol(*copyS);
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isSgExecutableStatement(func) && !isDVM_stat(func) && !isSPF_stat(func))
|
|
|
|
|
break;
|
|
|
|
|
if (func->variant() == CONTAINS_STMT)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void copyGroup(const map<string, FuncInfo*> &mapOfFunc, const vector<FuncInfo*> &toCopyGroups, map<FuncInfo*, callInfo> &funcInfoOfCall)
|
|
|
|
|
{
|
|
|
|
|
if (toCopyGroups.size() == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// function -> functions with interface to thisF
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> interfaceInfo;
|
|
|
|
|
|
|
|
|
|
for (auto& func: mapOfFunc)
|
|
|
|
|
for (auto& interf : func.second->interfaceBlocks)
|
|
|
|
|
interfaceInfo[interf.second].insert(func.second);
|
|
|
|
|
|
|
|
|
|
bool changed = true;
|
|
|
|
|
map<FuncInfo*, int> numCopyF;
|
|
|
|
|
|
|
|
|
|
map<string, map<SgStatement*, SgSymbol*>> toChangeSt;
|
|
|
|
|
map<string, map<SgExpression*, SgSymbol*>> toChangeEx;
|
|
|
|
|
map<string, set<string>> addedFuncDecl;
|
|
|
|
|
|
|
|
|
|
int iterCount = 0;
|
|
|
|
|
while (changed)
|
|
|
|
|
{
|
|
|
|
|
changed = false;
|
|
|
|
|
SgStatement::cleanParentStatsForExprs();
|
|
|
|
|
|
|
|
|
|
for (auto& currFunc : toCopyGroups)
|
|
|
|
|
{
|
|
|
|
|
auto info = funcInfoOfCall.find(currFunc);
|
|
|
|
|
if (info == funcInfoOfCall.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
if (numCopyF.find(currFunc) == numCopyF.end())
|
|
|
|
|
numCopyF[currFunc] = 1;
|
|
|
|
|
for (auto& varCall : info->second.variantCall)
|
|
|
|
|
{
|
|
|
|
|
int numCopy = numCopyF[currFunc];
|
|
|
|
|
if (varCall.copiedName.size() != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
|
if (SgFile::switchToFile(currFunc->fileName) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgStatement* pointToF = currFunc->funcPointer->GetOriginal();
|
|
|
|
|
|
|
|
|
|
SgSymbol* orig = pointToF->symbol();
|
|
|
|
|
string origName = orig->identifier();
|
|
|
|
|
origName = getOrigName(pointToF->fileName(), origName);
|
|
|
|
|
const string newName = checkSymbNameAndCorrect(origName + string("_spf_") + to_string(numCopy));
|
|
|
|
|
|
|
|
|
|
SgStatement* toMove = duplicateProcedure(pointToF, &newName, false, false, false);
|
|
|
|
|
|
|
|
|
|
varCall.copiedName = newName;
|
|
|
|
|
|
|
|
|
|
map<SgStatement*, SgStatement*> origCopySt;
|
|
|
|
|
map<SgExpression*, SgExpression*> origCopyEx;
|
|
|
|
|
// set line numbers and pointer to attributes
|
|
|
|
|
for (auto origStat = pointToF, copyStat = toMove;
|
|
|
|
|
origStat != pointToF->lastNodeOfStmt()->lexNext();
|
|
|
|
|
origStat = origStat->lexNext(), copyStat = copyStat->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (copyStat->variant() != origStat->variant())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
copyStat->setlineNumber(origStat->lineNumber());
|
|
|
|
|
copyStat->setLocalLineNumber(origStat->localLineNumber());
|
|
|
|
|
|
|
|
|
|
BIF_FILE_NAME(copyStat->thebif) = BIF_FILE_NAME(origStat->thebif);
|
|
|
|
|
if (origStat->numberOfAttributes() > 0)
|
|
|
|
|
copyStat->addAttributeTree(origStat->getAttribute(0));
|
|
|
|
|
origCopySt[origStat] = copyStat;
|
|
|
|
|
if (origStat->comments())
|
|
|
|
|
copyStat->setComments(origStat->comments());
|
|
|
|
|
|
|
|
|
|
for (int z = 0; z < 3; ++z)
|
|
|
|
|
fillOrigCopyEx(origStat->expr(z), copyStat->expr(z), origCopyEx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int varOfCall = PROC_HEDR;
|
|
|
|
|
//replace calls
|
|
|
|
|
for (auto& places : varCall.callPlaces)
|
|
|
|
|
{
|
|
|
|
|
if (get<1>(places) == PROC_STAT)
|
|
|
|
|
{
|
|
|
|
|
SgStatement* proc = (SgStatement*)get<0>(places);
|
|
|
|
|
if (SgFile::switchToFile(proc->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
SgSymbol* newS = &proc->symbol()->copy();
|
|
|
|
|
newS->changeName(newName.c_str());
|
|
|
|
|
toChangeSt[proc->fileName()][proc] = newS;
|
|
|
|
|
}
|
|
|
|
|
else if (get<1>(places) == FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
varOfCall = FUNC_HEDR;
|
|
|
|
|
SgExpression* proc = (SgExpression*)get<0>(places);
|
|
|
|
|
SgStatement* parent = (SgStatement*)get<2>(places);
|
|
|
|
|
|
|
|
|
|
if (parent == NULL)
|
|
|
|
|
parent = findReplacedExpression(proc);
|
|
|
|
|
checkNull(parent, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
if (SgFile::switchToFile(parent->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgSymbol* newS = &proc->symbol()->copy();
|
|
|
|
|
set<SgExpression*> allPlaces;
|
|
|
|
|
for (int z = 0; z < 3; ++z)
|
|
|
|
|
findAllFunctionCalls(parent->expr(z), varCall.callVariant, parent->fileName(), allPlaces);
|
|
|
|
|
if (allPlaces.size() == 0)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
newS->changeName(newName.c_str());
|
|
|
|
|
for (auto &elem : allPlaces)
|
|
|
|
|
toChangeEx[parent->fileName()][elem] = newS;
|
|
|
|
|
|
|
|
|
|
//duplicate names if parent func has implicit (none)
|
|
|
|
|
auto funcStat = getFuncStat(parent);
|
|
|
|
|
const string fName = funcStat->symbol()->identifier();
|
|
|
|
|
if (addedFuncDecl.find(fName) == addedFuncDecl.end())
|
|
|
|
|
addedFuncDecl[fName] = set<string>();
|
|
|
|
|
|
|
|
|
|
if (addedFuncDecl[fName].find(newName) == addedFuncDecl[fName].end())
|
|
|
|
|
{
|
|
|
|
|
findDeclAndDuplicate(funcStat, origName, newName, varOfCall);
|
|
|
|
|
addedFuncDecl[fName].insert(newName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//duplicate interfaces
|
|
|
|
|
auto itInterf = interfaceInfo.find(currFunc);
|
|
|
|
|
if (itInterf != interfaceInfo.end())
|
|
|
|
|
for (auto& func : itInterf->second)
|
|
|
|
|
findInterfaceBlockAndDuplicate(func->funcPointer->GetOriginal(), origName, newName, varOfCall);
|
|
|
|
|
|
|
|
|
|
// fill additional places to next replaces
|
2023-11-05 13:08:57 +03:00
|
|
|
for (int z = 0; z < currFunc->callsFromDetailed.size(); ++z)
|
2023-09-14 19:43:13 +03:00
|
|
|
{
|
2023-11-05 13:08:57 +03:00
|
|
|
pair<void*, int> place = currFunc->callsFromDetailed[z].pointerDetailCallsFrom;
|
2023-09-14 19:43:13 +03:00
|
|
|
if (place.second == PROC_STAT)
|
|
|
|
|
{
|
|
|
|
|
SgStatement* proc = (SgStatement*)place.first;
|
|
|
|
|
if (SgFile::switchToFile(proc->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
SgStatement* copyPoint = origCopySt[proc];
|
|
|
|
|
const string toFind = proc->symbol()->identifier();
|
|
|
|
|
|
|
|
|
|
auto itF = mapOfFunc.find(toFind.c_str());
|
|
|
|
|
if (itF == mapOfFunc.end())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
FuncInfo* toAdd = itF->second;
|
|
|
|
|
auto infoAdd = funcInfoOfCall.find(toAdd);
|
|
|
|
|
if (infoAdd == funcInfoOfCall.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
vector<void*> tmp;
|
2023-11-05 13:08:57 +03:00
|
|
|
infoAdd->second.variantCall.push_back(callVars(make_pair(copyPoint, PROC_STAT), tmp, currFunc->callsFromDetailed[z].parentForPointer));
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
else if (place.second == FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* proc = (SgExpression*)place.first;
|
2023-11-05 13:08:57 +03:00
|
|
|
SgStatement* parent = (SgStatement*)currFunc->callsFromDetailed[z].parentForPointer;
|
2023-09-14 19:43:13 +03:00
|
|
|
checkNull(parent, convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
if (SgFile::switchToFile(parent->fileName()) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
SgExpression* copyPoint = origCopyEx[proc];
|
|
|
|
|
const string toFind = proc->symbol()->identifier();
|
|
|
|
|
|
|
|
|
|
auto itF = mapOfFunc.find(toFind.c_str());
|
|
|
|
|
if (itF == mapOfFunc.end())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
FuncInfo* toAdd = itF->second;
|
|
|
|
|
auto infoAdd = funcInfoOfCall.find(toAdd);
|
|
|
|
|
if (infoAdd == funcInfoOfCall.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
vector<void*> tmp;
|
2023-11-05 13:08:57 +03:00
|
|
|
infoAdd->second.variantCall.push_back(callVars(make_pair(copyPoint, FUNC_CALL), tmp, currFunc->callsFromDetailed[z].parentForPointer));
|
2023-09-14 19:43:13 +03:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numCopyF[currFunc]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++iterCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& elem : toChangeSt)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(elem.first) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto& toSet : elem.second)
|
|
|
|
|
toSet.first->setSymbol(*toSet.second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& elem : toChangeEx)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(elem.first) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto& toSet : elem.second)
|
|
|
|
|
toSet.first->setSymbol(*toSet.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool checkForData(FuncInfo* info, map<string, vector<Messages>>& messages)
|
|
|
|
|
{
|
|
|
|
|
bool retVal = true;
|
|
|
|
|
if (info->isMain || info->isInterface)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
SgStatement* funcP = info->funcPointer->GetOriginal();
|
|
|
|
|
if (!funcP->switchToFile())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto st = funcP; st != funcP->lastNodeOfStmt(); st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == CONTAINS_STMT)
|
|
|
|
|
break;
|
|
|
|
|
if (isSgExecutableStatement(st))
|
|
|
|
|
break;
|
|
|
|
|
if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* list = st->expr(0);
|
|
|
|
|
while (list)
|
|
|
|
|
{
|
|
|
|
|
auto value = list->lhs();
|
|
|
|
|
if (value->variant() == ASSGN_OP)
|
|
|
|
|
{
|
|
|
|
|
wstring bufE, bufR;
|
|
|
|
|
__spf_printToLongBuf(bufE, L"SAVE or DATA operators prevent function duplication: variable '%s'",
|
|
|
|
|
to_wstring(value->lhs()->symbol()->identifier()).c_str());
|
|
|
|
|
__spf_printToLongBuf(bufR, R174, to_wstring(value->lhs()->symbol()->identifier()).c_str());
|
|
|
|
|
|
|
|
|
|
messages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), bufR, bufE, 2013));
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
else if (value->symbol() && (value->symbol()->attributes() & DATA_BIT))
|
|
|
|
|
{
|
|
|
|
|
wstring bufE, bufR;
|
|
|
|
|
__spf_printToLongBuf(bufE, L"SAVE or DATA operators prevent function duplication: variable '%s'", to_wstring(value->symbol()->identifier()).c_str());
|
|
|
|
|
__spf_printToLongBuf(bufR, R174, to_wstring(value->symbol()->identifier()).c_str());
|
|
|
|
|
|
|
|
|
|
messages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), bufR, bufE, 2013));
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
list = list->rhs();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (st->variant() == SAVE_DECL || st->variant() == DATA_DECL)
|
|
|
|
|
{
|
|
|
|
|
wstring bufE, bufR;
|
|
|
|
|
__spf_printToLongBuf(bufE, L"SAVE or DATA operators prevent function duplication");
|
|
|
|
|
__spf_printToLongBuf(bufR, R173);
|
|
|
|
|
|
|
|
|
|
messages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), bufR, bufE, 2012));
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool duplicateFunctions(const map<string, vector<FuncInfo*>> &allFuncs, const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCall,
|
|
|
|
|
map<string, vector<Messages>>& messages)
|
|
|
|
|
{
|
|
|
|
|
map<string, FuncInfo*> mapOfFunc;
|
|
|
|
|
createMapOfFunc(allFuncs, mapOfFunc);
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, callInfo> funcInfoOfCall;
|
|
|
|
|
vector<FuncInfo*> toCopy = detect(allFuncs, mapOfFunc, funcInfoOfCall, arrayLinksByFuncCall);
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> toCopyGroups = groupByMainCall(toCopy, mapOfFunc);
|
|
|
|
|
|
|
|
|
|
vector<FuncInfo*> toCopyVec;
|
|
|
|
|
for (auto& elem : toCopyGroups)
|
|
|
|
|
toCopyVec.push_back(elem.first);
|
|
|
|
|
|
|
|
|
|
for (auto& elem : toCopyGroups)
|
|
|
|
|
for (auto &inG : elem.second)
|
|
|
|
|
toCopyVec.push_back(inG);
|
|
|
|
|
|
|
|
|
|
bool checkOk = true;
|
|
|
|
|
//check for save vars
|
|
|
|
|
for (auto& func : toCopyVec)
|
|
|
|
|
{
|
|
|
|
|
bool res = checkForData(func, messages);
|
|
|
|
|
checkOk = checkOk && res;
|
|
|
|
|
}
|
|
|
|
|
if (checkOk)
|
|
|
|
|
copyGroup(mapOfFunc, toCopyVec, funcInfoOfCall);
|
|
|
|
|
return checkOk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void changeFuncNameInDvmDirs(SgExpression* ex, const string& to, const string& from, map<SgSymbol*, string>& changed)
|
|
|
|
|
{
|
|
|
|
|
if (ex)
|
|
|
|
|
{
|
|
|
|
|
if (ex->variant() == VAR_REF)
|
|
|
|
|
{
|
|
|
|
|
auto s = ex->symbol();
|
|
|
|
|
if (s->identifier() == from || from.find("::") != string::npos && from.find(s->identifier()) != string::npos)
|
|
|
|
|
{
|
|
|
|
|
changed[s] = s->identifier();
|
|
|
|
|
s->changeName(to.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
changeFuncNameInDvmDirs(ex->lhs(), to, from, changed);
|
|
|
|
|
changeFuncNameInDvmDirs(ex->rhs(), to, from, changed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<SgSymbol*, string> changeFuncNameInDvmDirs(const string& to, const string &from, SgStatement* func)
|
|
|
|
|
{
|
|
|
|
|
map<SgSymbol*, string> changed;
|
|
|
|
|
SgStatement* st = func;
|
|
|
|
|
SgStatement* last = st->lastNodeOfStmt();
|
|
|
|
|
while (st != last)
|
|
|
|
|
{
|
|
|
|
|
if (isDVM_stat(st))
|
|
|
|
|
for (int z = 0; z < 3; ++z)
|
|
|
|
|
changeFuncNameInDvmDirs(st->expr(z), to, from, changed);
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
}
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<FuncInfo*, set<FuncInfo*>> getUniqCopies(const vector<FuncInfo*> &toCmp)
|
|
|
|
|
{
|
|
|
|
|
map<string, set<FuncInfo*>> dict;
|
|
|
|
|
string cmpName = "testCmpName";
|
|
|
|
|
for (auto& elem : toCmp)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol *s = elem->funcPointer->GetOriginal()->symbol();
|
|
|
|
|
string saveName = s->identifier();
|
|
|
|
|
s->changeName(cmpName.c_str());
|
|
|
|
|
|
|
|
|
|
map<SgSymbol*, string> changed;
|
|
|
|
|
if (elem->funcPointer->GetOriginal()->variant() == FUNC_HEDR)
|
|
|
|
|
changed = changeFuncNameInDvmDirs(cmpName, saveName, elem->funcPointer->GetOriginal());
|
|
|
|
|
|
|
|
|
|
const char* buf = elem->funcPointer->GetOriginal()->unparse();
|
|
|
|
|
dict[buf].insert(elem);
|
|
|
|
|
|
|
|
|
|
s->changeName(saveName.c_str());
|
|
|
|
|
for (auto& elem : changed)
|
|
|
|
|
elem.first->changeName(elem.second.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> uniq;
|
|
|
|
|
for (auto& elem : dict)
|
|
|
|
|
{
|
|
|
|
|
auto it = elem.second.begin();
|
|
|
|
|
FuncInfo* base = *it;
|
|
|
|
|
uniq[base] = set<FuncInfo*>();
|
|
|
|
|
for (it++; it != elem.second.end(); it++)
|
|
|
|
|
uniq[base].insert(*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return uniq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static map<string, set<FuncInfo*>> removed;
|
|
|
|
|
static map<string, set<SgStatement*>> copied;
|
|
|
|
|
static map<string, string> newNamesOfUniqCopies;
|
|
|
|
|
map<SgSymbol*, pair<string, string>> replaced;
|
|
|
|
|
static map<string, set<SgStatement*>> hiddenInterfaceBlocks;
|
|
|
|
|
static map<string, set<SgStatement*>> unitedDecls;
|
|
|
|
|
|
|
|
|
|
static bool removeThisFunctions(const string &file, const map<FuncInfo*, set<FuncInfo*>> &uniqCopies, const vector<FuncInfo*>& toRem)
|
|
|
|
|
{
|
|
|
|
|
bool wasRemoved = false;
|
|
|
|
|
for (auto& rem : toRem)
|
|
|
|
|
{
|
|
|
|
|
if (uniqCopies.find(rem) == uniqCopies.end() && removed[file].find(rem) == removed[file].end())
|
|
|
|
|
{
|
|
|
|
|
SgStatement* orig = rem->funcPointer->GetOriginal();
|
|
|
|
|
SgStatement* last = orig->lastNodeOfStmt();
|
|
|
|
|
while (orig != last)
|
|
|
|
|
{
|
|
|
|
|
orig->setVariant(orig->variant() * -1);
|
|
|
|
|
orig = orig->lexNext();
|
|
|
|
|
}
|
|
|
|
|
wasRemoved = true;
|
|
|
|
|
removed[file].insert(rem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return wasRemoved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool removeThisFunctions(const string& file, FuncInfo* toRem)
|
|
|
|
|
{
|
|
|
|
|
vector<FuncInfo*> tmp = { toRem };
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> info;
|
|
|
|
|
return removeThisFunctions(file, info, tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void restoreFunctions(const string &file)
|
|
|
|
|
{
|
|
|
|
|
for (auto& elem : removed[file])
|
|
|
|
|
{
|
|
|
|
|
SgStatement* orig = elem->funcPointer->GetOriginal();
|
|
|
|
|
SgStatement* last = orig->lastNodeOfStmt();
|
|
|
|
|
while (orig != last)
|
|
|
|
|
{
|
|
|
|
|
orig->setVariant(orig->variant() * -1);
|
|
|
|
|
orig = orig->lexNext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
removed[file].clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void createCopies(const string &file, const string &baseName, const map<FuncInfo*, set<FuncInfo*>> &uniqCopies)
|
|
|
|
|
{
|
|
|
|
|
int newNum = 0;
|
|
|
|
|
for (auto& toCopy : uniqCopies)
|
|
|
|
|
{
|
|
|
|
|
const string newName = newNum > 0 ? baseName + "_spfr_" + to_string(newNum) : baseName;
|
|
|
|
|
++newNum;
|
|
|
|
|
|
|
|
|
|
const string clearNameS = getClearName(newName);
|
|
|
|
|
SgStatement* duplicated = duplicateProcedure(toCopy.first->funcPointer->GetOriginal(), &clearNameS, true, true);
|
|
|
|
|
if (duplicated->variant() == FUNC_HEDR)
|
|
|
|
|
changeFuncNameInDvmDirs(clearNameS, toCopy.first->funcPointer->GetOriginal()->symbol()->identifier(), duplicated);
|
|
|
|
|
|
|
|
|
|
copied[toCopy.first->funcPointer->GetOriginal()->fileName()].insert(duplicated);
|
|
|
|
|
newNamesOfUniqCopies[toCopy.first->funcName] = newName;
|
|
|
|
|
for (auto &theSame : toCopy.second)
|
|
|
|
|
newNamesOfUniqCopies[theSame->funcName] = newName;
|
|
|
|
|
|
|
|
|
|
removeThisFunctions(file, toCopy.first);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void doReplacements(SgSymbol* s, map<SgSymbol*, pair<string, string>> &replaced)
|
|
|
|
|
{
|
|
|
|
|
auto itR = replaced.find(s);
|
|
|
|
|
if (itR == replaced.end())
|
|
|
|
|
{
|
|
|
|
|
auto it = newNamesOfUniqCopies.find(s->identifier());
|
|
|
|
|
if (it != newNamesOfUniqCopies.end())
|
|
|
|
|
{
|
|
|
|
|
s->changeName(it->second.c_str());
|
|
|
|
|
replaced.insert(itR, make_pair(s, *it));
|
|
|
|
|
}
|
|
|
|
|
else // for modules and contains?
|
|
|
|
|
{
|
|
|
|
|
vector<string> toReplace;
|
|
|
|
|
string ident = s->identifier();
|
|
|
|
|
for (auto& elem : newNamesOfUniqCopies)
|
|
|
|
|
if (getClearName(elem.first) == ident)
|
|
|
|
|
toReplace.push_back(elem.second);
|
|
|
|
|
|
|
|
|
|
if (toReplace.size() == 1)
|
|
|
|
|
{
|
|
|
|
|
s->changeName(getClearName(toReplace[0]).c_str());
|
|
|
|
|
replaced.insert(itR, make_pair(s, make_pair(ident, toReplace[0])));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void doReplacements(SgExpression* ex, map<SgSymbol*, pair<string, string>> *replaced)
|
|
|
|
|
{
|
|
|
|
|
if (ex)
|
|
|
|
|
{
|
|
|
|
|
if (ex->variant() == FUNC_CALL)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* s = ex->symbol();
|
|
|
|
|
if (replaced)
|
|
|
|
|
doReplacements(s, *replaced);
|
|
|
|
|
else
|
|
|
|
|
doReplacements(s, ::replaced);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
doReplacements(ex->lhs(), replaced);
|
|
|
|
|
doReplacements(ex->rhs(), replaced);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void doReplacements(SgStatement* st, SgStatement* last, map<SgSymbol*, pair<string, string>> *replaced = NULL)
|
|
|
|
|
{
|
|
|
|
|
while (st != last)
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == PROC_STAT)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol *s = st->symbol();
|
|
|
|
|
|
|
|
|
|
if (replaced)
|
|
|
|
|
doReplacements(s, *replaced);
|
|
|
|
|
else
|
|
|
|
|
doReplacements(s, ::replaced);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int z = 0; z < 3; ++z)
|
|
|
|
|
doReplacements(st->expr(z), replaced);
|
|
|
|
|
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void removeUnnecessaryReplacedFunctionDecls(SgStatement* st, SgStatement* last)
|
|
|
|
|
{
|
|
|
|
|
map<int, pair<string, string>> replacedIdx;
|
|
|
|
|
for (auto& elem : replaced)
|
|
|
|
|
{
|
|
|
|
|
if (replacedIdx.find(elem.first->id()) != replacedIdx.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
replacedIdx[elem.first->id()] = elem.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (replacedIdx.size() == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SgStatement* orig = st;
|
|
|
|
|
while (st != last)
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == CONTAINS_STMT)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90)
|
|
|
|
|
{
|
|
|
|
|
SgExpression* ex = st->expr(0);
|
|
|
|
|
|
|
|
|
|
/*while (ex)
|
|
|
|
|
{
|
|
|
|
|
auto arg = ex->lhs();
|
|
|
|
|
if (arg && arg->symbol())
|
|
|
|
|
{
|
|
|
|
|
auto s = arg->symbol();
|
|
|
|
|
auto it = replacedIdx.find(s->id());
|
|
|
|
|
|
|
|
|
|
//restore original name and copy symbol
|
|
|
|
|
if (it != replacedIdx.end())
|
|
|
|
|
{
|
|
|
|
|
auto copy = &s->copy();
|
|
|
|
|
copy->changeName(it->second.first.c_str());
|
|
|
|
|
arg->setSymbol(copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ex = ex->rhs();
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
bool hasReplaces = false;
|
|
|
|
|
while (ex)
|
|
|
|
|
{
|
|
|
|
|
auto arg = ex->lhs();
|
|
|
|
|
if (arg && arg->symbol())
|
|
|
|
|
{
|
|
|
|
|
auto s = arg->symbol();
|
|
|
|
|
auto it = replacedIdx.find(s->id());
|
|
|
|
|
|
|
|
|
|
//restore original name and copy symbol
|
|
|
|
|
if (it != replacedIdx.end())
|
|
|
|
|
{
|
|
|
|
|
hasReplaces = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ex = ex->rhs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasReplaces)
|
|
|
|
|
{
|
|
|
|
|
auto copy = st->copy();
|
|
|
|
|
//united decls
|
|
|
|
|
ex = copy.expr(0);
|
|
|
|
|
SgExpression* prev = NULL;
|
|
|
|
|
|
|
|
|
|
set<string> has;
|
|
|
|
|
while (ex)
|
|
|
|
|
{
|
|
|
|
|
auto arg = ex->lhs();
|
|
|
|
|
if (arg && arg->symbol())
|
|
|
|
|
{
|
|
|
|
|
auto s = arg->symbol();
|
|
|
|
|
if (has.find(s->identifier()) != has.end())
|
|
|
|
|
{
|
|
|
|
|
if (prev)
|
|
|
|
|
prev->setRhs(ex->rhs());
|
|
|
|
|
else
|
|
|
|
|
copy.setExpression(0, ex->rhs());
|
|
|
|
|
|
|
|
|
|
ex = ex->rhs();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
has.insert(s->identifier());
|
|
|
|
|
}
|
|
|
|
|
prev = ex;
|
|
|
|
|
ex = ex->rhs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
st->insertStmtBefore(copy, *st->controlParent());
|
|
|
|
|
st->setVariant(st->variant() * -1);
|
|
|
|
|
unitedDecls[current_file->filename()].insert(st);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
st = st->lexNext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void hiddenInterfaces(SgStatement* func)
|
|
|
|
|
{
|
|
|
|
|
SgStatement* last = func;
|
|
|
|
|
const string fileName = func->fileName();
|
|
|
|
|
|
|
|
|
|
for (auto st = func->lexNext(); st != last; st = st->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (st->variant() == CONTAINS_STMT)
|
|
|
|
|
break;
|
|
|
|
|
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (st->variant() == INTERFACE_STMT)
|
|
|
|
|
{
|
|
|
|
|
int total = 0;
|
|
|
|
|
map<string, set<SgStatement*>> objects;
|
|
|
|
|
SgStatement* iEnd = st->lastNodeOfStmt();
|
|
|
|
|
for (auto iSt = st->lexNext(); iSt != iEnd; iSt = iSt->lexNext())
|
|
|
|
|
{
|
|
|
|
|
if (iSt->variant() == PROC_HEDR || iSt->variant() == FUNC_HEDR)
|
|
|
|
|
objects[iSt->symbol()->identifier()].insert(iSt);
|
|
|
|
|
total++;
|
|
|
|
|
iSt = iSt->lastNodeOfStmt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (objects.size() != total)
|
|
|
|
|
{
|
|
|
|
|
for (auto& uniq : objects)
|
|
|
|
|
{
|
|
|
|
|
int first = 0;
|
|
|
|
|
for (auto& obj : uniq.second)
|
|
|
|
|
{
|
|
|
|
|
if (first)
|
|
|
|
|
{
|
|
|
|
|
obj->setVariant(-obj->variant());
|
|
|
|
|
hiddenInterfaceBlocks[fileName].insert(obj);
|
|
|
|
|
--total;
|
|
|
|
|
}
|
|
|
|
|
++first;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (total == 0)
|
|
|
|
|
{
|
|
|
|
|
st->setVariant(-st->variant());
|
|
|
|
|
hiddenInterfaceBlocks[fileName].insert(st);
|
|
|
|
|
}
|
|
|
|
|
st = iEnd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void replaceNewNames(const map<string, vector<FuncInfo*>> &allFuncs)
|
|
|
|
|
{
|
|
|
|
|
for (auto& byfile : allFuncs)
|
|
|
|
|
{
|
|
|
|
|
if (SgFile::switchToFile(byfile.first) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto& func : byfile.second)
|
|
|
|
|
{
|
|
|
|
|
if (func->funcPointer->GetOriginal()->variant() < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
SgStatement* p = func->funcPointer->GetOriginal();
|
|
|
|
|
doReplacements(p, p->lastNodeOfStmt());
|
|
|
|
|
hiddenInterfaces(p);
|
|
|
|
|
removeUnnecessaryReplacedFunctionDecls(p, p->lastNodeOfStmt());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map<SgSymbol*, pair<string, string>> replaced_tmp;
|
|
|
|
|
if (copied.find(byfile.first) != copied.end())
|
|
|
|
|
{
|
|
|
|
|
for (auto& func : copied[byfile.first])
|
|
|
|
|
doReplacements(func, func->lastNodeOfStmt(), &replaced_tmp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removeCopies(const map<string, vector<FuncInfo*>>& allFuncs)
|
|
|
|
|
{
|
|
|
|
|
bool changed = true;
|
|
|
|
|
while (changed)
|
|
|
|
|
{
|
|
|
|
|
changed = false;
|
|
|
|
|
for (auto& byFile : allFuncs)
|
|
|
|
|
{
|
|
|
|
|
string fileS = byFile.first;
|
|
|
|
|
if (SgFile::switchToFile(fileS) == -1)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (auto& func : byFile.second)
|
|
|
|
|
{
|
|
|
|
|
if (func->fullCopiesOfThisFunction.size() && removed[fileS].find(func) == removed[fileS].end())
|
|
|
|
|
{
|
|
|
|
|
map<FuncInfo*, set<FuncInfo*>> uniqCopies = getUniqCopies(func->fullCopiesOfThisFunction);
|
|
|
|
|
if (uniqCopies.size() == func->fullCopiesOfThisFunction.size())
|
|
|
|
|
continue;
|
|
|
|
|
if (uniqCopies.size() == 0)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
bool ret1 = removeThisFunctions(fileS, uniqCopies, func->fullCopiesOfThisFunction);
|
|
|
|
|
bool ret2 = removeThisFunctions(fileS, func);
|
|
|
|
|
changed = ret1 || ret2;
|
|
|
|
|
if (changed)
|
|
|
|
|
createCopies(fileS, func->funcName, uniqCopies);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (changed)
|
|
|
|
|
replaceNewNames(allFuncs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void restoreCopies(SgFile* file)
|
|
|
|
|
{
|
|
|
|
|
const string fileName = file->filename();
|
|
|
|
|
|
|
|
|
|
auto itU = unitedDecls.find(fileName);
|
|
|
|
|
if (itU != unitedDecls.end())
|
|
|
|
|
{
|
|
|
|
|
for (auto& st : itU->second)
|
|
|
|
|
{
|
|
|
|
|
st->setVariant(st->variant() * -1);
|
|
|
|
|
auto prev = st->lexPrev();
|
|
|
|
|
prev->deleteStmt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unitedDecls.erase(itU);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restoreFunctions(fileName);
|
|
|
|
|
for (auto& elem : copied[file->filename()])
|
|
|
|
|
elem->deleteStmt();
|
|
|
|
|
copied[file->filename()].clear();
|
|
|
|
|
|
|
|
|
|
for (auto& elem : replaced)
|
|
|
|
|
elem.first->changeName(elem.second.first.c_str());
|
|
|
|
|
replaced.clear();
|
|
|
|
|
newNamesOfUniqCopies.clear();
|
|
|
|
|
|
|
|
|
|
auto it = hiddenInterfaceBlocks.find(fileName);
|
|
|
|
|
if (it != hiddenInterfaceBlocks.end())
|
|
|
|
|
{
|
|
|
|
|
for (auto& obj : it->second)
|
|
|
|
|
if (obj->variant() < 0)
|
|
|
|
|
obj->setVariant(-obj->variant());
|
|
|
|
|
|
|
|
|
|
hiddenInterfaceBlocks.erase(it);
|
|
|
|
|
}
|
|
|
|
|
}
|