4326 lines
136 KiB
C++
4326 lines
136 KiB
C++
#include "leak_detector.h"
|
|
|
|
#include "dvm.h"
|
|
#include "acc_analyzer.h"
|
|
#include "calls.h"
|
|
#include <fstream>
|
|
#include <stdint.h>
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
using std::map;
|
|
using std::list;
|
|
using std::make_pair;
|
|
using std::set;
|
|
using std::pair;
|
|
|
|
#if __SPF
|
|
using std::wstring;
|
|
#include "../_src/Utils/AstWrapper.h"
|
|
#include "../_src/Utils/utils.h"
|
|
#include "../_src/Utils/errors.h"
|
|
|
|
static pair<wstring, string> getText(const char *s, const wchar_t *s1, const char *t, int num, SgStatement *stmt, int &line)
|
|
{
|
|
pair<wstring, string> ret;
|
|
|
|
wchar_t bufW[1024];
|
|
#if _WIN32
|
|
swprintf(bufW, s1, to_wstring(t).c_str());
|
|
#else
|
|
swprintf(bufW, 1024, s1, to_wstring(t).c_str());
|
|
#endif
|
|
ret.first = bufW;
|
|
|
|
char buf[1024];
|
|
sprintf(buf, s, t);
|
|
ret.second = buf;
|
|
|
|
line = stmt->lineNumber();
|
|
if (line == 0)
|
|
{
|
|
line = 1;
|
|
if (stmt->variant() == DVM_PARALLEL_ON_DIR)
|
|
{
|
|
line = stmt->lexNext()->lineNumber();
|
|
ret.first += RR158_1;
|
|
ret.second += " for this loop";
|
|
}
|
|
}
|
|
|
|
if (stmt->variant() == SPF_ANALYSIS_DIR)
|
|
{
|
|
ret.first += RR158_1;
|
|
ret.second += " for this loop";
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline bool ifVarIsLoopSymb(SgStatement *stmt, const string symb)
|
|
{
|
|
bool ret = false;
|
|
if (stmt == NULL)
|
|
return ret;
|
|
|
|
int var = stmt->variant();
|
|
if (var == SPF_ANALYSIS_DIR || var == SPF_PARALLEL_DIR || var == SPF_TRANSFORM_DIR || var == SPF_PARALLEL_REG_DIR || var == SPF_END_PARALLEL_REG_DIR)
|
|
stmt = stmt->lexNext();
|
|
|
|
SgForStmt *forS = isSgForStmt(stmt);
|
|
if (forS)
|
|
{
|
|
SgStatement *end = forS->lastNodeOfStmt();
|
|
for (; stmt != end && !ret; stmt = stmt->lexNext())
|
|
if (stmt->variant() == FOR_NODE)
|
|
if (isSgForStmt(stmt)->symbol()->identifier() == symb)
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
template<typename fillType> void fillPrivatesFromComment(Statement *st, std::set<fillType> &privates);
|
|
|
|
inline void Warning(const char *s, const wchar_t *s1, const char *t, int num, SgStatement *stmt)
|
|
{
|
|
//TODO: is it correct?
|
|
if (stmt == NULL)
|
|
return;
|
|
|
|
if (num == PRIVATE_ANALYSIS_REMOVE_VAR)
|
|
{
|
|
SgStatement *found = SgStatement::getStatementByFileAndLine(string(stmt->fileName()), stmt->lineNumber());
|
|
if (found != NULL)
|
|
{
|
|
if (ifVarIsLoopSymb(found, t))
|
|
return;
|
|
}
|
|
|
|
set<string> privates;
|
|
fillPrivatesFromComment(new Statement(stmt), privates);
|
|
if (privates.find(t) != privates.end())
|
|
return;
|
|
}
|
|
|
|
|
|
int line;
|
|
auto retVal = getText(s, s1, t, num, stmt, line);
|
|
printLowLevelWarnings(stmt->fileName(), line, retVal.first.c_str(), retVal.second.c_str(), 1029);
|
|
}
|
|
|
|
inline void Note(const char *s, const wchar_t *s1, const char *t, int num, SgStatement *stmt)
|
|
{
|
|
int line;
|
|
auto retVal = getText(s, s1, t, num, stmt, line);
|
|
printLowLevelNote(stmt->fileName(), line, retVal.first.c_str(), retVal.second.c_str(), 1030);
|
|
}
|
|
#endif
|
|
|
|
// local functions
|
|
static ControlFlowItem* getControlFlowList(SgStatement*, SgStatement*, ControlFlowItem**, SgStatement**, doLoops*, CallData*, CommonData*);
|
|
static ControlFlowItem* processOneStatement(SgStatement** stmt, ControlFlowItem** pred, ControlFlowItem **list, ControlFlowItem* oldcur, doLoops*, CallData*, CommonData*);
|
|
static ControlFlowItem* switchItem(SgStatement* stmt, ControlFlowItem* empty, SgStatement** lastAnStmt, doLoops* loops, CallData* calls, CommonData*);
|
|
static ControlFlowItem* ifItem(SgStatement*, ControlFlowItem*, SgStatement** lastAnStmt, doLoops* loops, bool ins, CallData*, CommonData*);
|
|
static void setLeaders(ControlFlowItem*);
|
|
static void clearList(ControlFlowItem*);
|
|
static void fillLabelJumps(ControlFlowItem*);
|
|
static SgExpression* GetProcedureArgument(bool isF, void* f, int i);
|
|
static int GetNumberOfArguments(bool isF, void* f);
|
|
#if ACCAN_DEBUG
|
|
static void printControlFlowList(ControlFlowItem*, ControlFlowItem* last = NULL);
|
|
#endif
|
|
|
|
//static ControlFlowGraph* GetControlFlowGraphWithCalls(bool, SgStatement*, CallData*, CommonData*);
|
|
//static void FillCFGSets(ControlFlowGraph*);
|
|
static void FillPrivates(ControlFlowGraph*);
|
|
static ControlFlowItem* AddFunctionCalls(SgStatement*, CallData*, ControlFlowItem**, CommonData*);
|
|
|
|
const char* is_correct = NULL;
|
|
const char* failed_proc_name = NULL;
|
|
static PrivateDelayedItem* privateDelayedList = NULL;
|
|
static AnalysedCallsList* currentProcedure = NULL;
|
|
static AnalysedCallsList* mainProcedure = NULL;
|
|
static DoLoopDataList* doLoopList = NULL;
|
|
static CommonData* pCommons;
|
|
static CallData* pCalls;
|
|
|
|
int total_privates = 0;
|
|
int total_pl = 0;
|
|
|
|
static const IntrinsicSubroutineData intrinsicData[] = {
|
|
{"date_and_time", 4, { {-1, "date", INTRINSIC_OUT}, {-1, "time", INTRINSIC_OUT }, {-1, "zone", INTRINSIC_OUT }, {-1, "values", INTRINSIC_OUT } } },
|
|
{"mod", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN} } },
|
|
{"dvtime", 0, {}},
|
|
{"abs", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"max", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN} } },
|
|
{"min", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN} } },
|
|
{"wtime", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"dble", 1, { {1, NULL, INTRINSIC_IN } } },
|
|
{"dabs", 1, { {1, NULL, INTRINSIC_IN } } },
|
|
{"dmax1", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN } } },
|
|
{"dmin1", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN } } },
|
|
{"dsqrt", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"dcos", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"datan2", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN} } },
|
|
{"dsign", 2, { {1, NULL, INTRINSIC_IN}, {2, NULL, INTRINSIC_IN} } },
|
|
{"dlog", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"dexp", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"omp_get_wtime", 0, {}},
|
|
{"sqrt", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"int", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"iabs", 1, { {1, NULL, INTRINSIC_IN} } },
|
|
{"fnpr", 4, { {1, NULL, INTRINSIC_IN},{ 2, NULL, INTRINSIC_IN },{ 3, NULL, INTRINSIC_IN },{ 4, NULL, INTRINSIC_IN } } },
|
|
{"isnan", 1, { {1, NULL, INTRINSIC_IN } } }
|
|
};
|
|
|
|
//TODO: it does not work
|
|
//static map<SgStatement*, tuple<ControlFlowGraph*, CallData*, CommonData*>> CFG_cache;
|
|
|
|
|
|
static bool isIntrinsicFunctionNameACC(char* name)
|
|
{
|
|
#if USE_INTRINSIC_DVM_LIST
|
|
return isIntrinsicFunctionName(name);
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
int SwitchFile(int file_id)
|
|
{
|
|
if (file_id == current_file_id || file_id == -1)
|
|
return file_id;
|
|
int stored_file_id = current_file_id;
|
|
current_file_id = file_id;
|
|
current_file = &(CurrentProject->file(current_file_id));
|
|
return stored_file_id;
|
|
}
|
|
|
|
SgStatement * lastStmtOfDoACC(SgStatement *stdo)
|
|
{
|
|
// is a copied function
|
|
SgStatement *st;
|
|
// second version (change 04.03.08)
|
|
st = stdo;
|
|
RE: st = st->lastNodeOfStmt();
|
|
if ((st->variant() == FOR_NODE) || (st->variant() == WHILE_NODE))
|
|
goto RE;
|
|
|
|
else if (st->variant() == LOGIF_NODE)
|
|
return(st->lexNext());
|
|
|
|
else
|
|
return(st);
|
|
|
|
}
|
|
|
|
#ifdef __SPF
|
|
bool IsPureProcedureACC(SgSymbol* s)
|
|
#else
|
|
static bool IsPureProcedureACC(SgSymbol* s)
|
|
#endif
|
|
{
|
|
// is a copied function
|
|
SgSymbol *shedr = NULL;
|
|
|
|
shedr = GetProcedureHeaderSymbol(s);
|
|
if (shedr)
|
|
return(shedr->attributes() & PURE_BIT);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static bool IsUserFunctionACC(SgSymbol* s)
|
|
{
|
|
// is a copied function
|
|
return(s->attributes() & USER_PROCEDURE_BIT);
|
|
}
|
|
|
|
static const IntrinsicSubroutineData* IsAnIntrinsicSubroutine(const char* name)
|
|
{
|
|
for (int i = 0; i < sizeof(intrinsicData) / sizeof(intrinsicData[0]); i++)
|
|
if (strcmp(name, intrinsicData[i].name) == 0)
|
|
return &(intrinsicData[i]);
|
|
return NULL;
|
|
}
|
|
|
|
static SgExpression* CheckIntrinsicParameterFlag(const char* name, int arg, SgExpression* p, unsigned char flag)
|
|
{
|
|
const IntrinsicSubroutineData* info = IsAnIntrinsicSubroutine(name);
|
|
if (!info)
|
|
return NULL; //better avoid this
|
|
for (int i = 0; i < info->args; i++)
|
|
{
|
|
const IntrinsicParameterData* pd = &(info->parameters[i]);
|
|
if (pd->index == arg + 1)
|
|
return (pd->status & flag) != 0 ? p : NULL;
|
|
|
|
SgKeywordArgExp* kw = isSgKeywordArgExp(p);
|
|
if (kw)
|
|
{
|
|
SgExpression* a = kw->arg();
|
|
SgExpression* val = kw->value();
|
|
if (pd->name && strcmp(a->unparse(), pd->name) == 0)
|
|
return (pd->status & flag) != 0 ? val : NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
/*
|
|
//For parameters replacements in expressions
|
|
//#ifdef __SPF
|
|
|
|
VarsKeeper varsKeeper;
|
|
|
|
SgExpression* GetValueOfVar(SgExpression* var)
|
|
{
|
|
return varsKeeper.GetValueOfVar(var);
|
|
}
|
|
|
|
void VarsKeeper::GatherVars(SgStatement* start)
|
|
{
|
|
pCommons = &(data->commons);
|
|
pCalls = &(data->calls);
|
|
currentProcedure = data->calls.AddHeader(start, false, start->symbol());
|
|
mainProcedure = currentProcedure;
|
|
//stage 1: preparing graph data
|
|
data->graph = GetControlFlowGraphWithCalls(true, start, &(data->calls), &(data->commons));
|
|
data->calls.AssociateGraphWithHeader(start, data->graph);
|
|
data->commons.MarkEndOfCommon(currentProcedure);
|
|
//calls.printControlFlows();
|
|
//stage 2: data flow analysis
|
|
FillCFGSets(data->graph);
|
|
//stage 3: fulfilling loop data
|
|
FillPrivates(data->graph);
|
|
|
|
if (privateDelayedList)
|
|
delete privateDelayedList;
|
|
privateDelayedList = NULL;
|
|
}
|
|
|
|
SgExpression* VarsKeeper::GetValueOfVar(SgExpression* var)
|
|
{
|
|
FuncData* curData = data;
|
|
}
|
|
|
|
//#endif
|
|
*/
|
|
|
|
|
|
|
|
void SetUpVars(CommonData* commons, CallData* calls, AnalysedCallsList* m, DoLoopDataList* list)
|
|
{
|
|
pCommons = commons;
|
|
pCalls = calls;
|
|
currentProcedure = m;
|
|
mainProcedure = currentProcedure;
|
|
doLoopList = list;
|
|
}
|
|
|
|
AnalysedCallsList* GetCurrentProcedure()
|
|
{
|
|
return currentProcedure;
|
|
}
|
|
//interprocedural analysis, called for main procedure
|
|
void Private_Vars_Analyzer(SgStatement* start)
|
|
{
|
|
#ifndef __SPF
|
|
if (!options.isOn(PRIVATE_ANALYSIS)) {
|
|
return;
|
|
}
|
|
#endif
|
|
CallData calls;
|
|
CommonData commons;
|
|
DoLoopDataList doloopList;
|
|
SetUpVars(&commons, &calls, calls.AddHeader(start, false, start->symbol(), current_file_id), &doloopList);
|
|
|
|
//stage 1: preparing graph data
|
|
ControlFlowGraph* CGraph = GetControlFlowGraphWithCalls(true, start, &calls, &commons);
|
|
calls.AssociateGraphWithHeader(start, CGraph);
|
|
commons.MarkEndOfCommon(currentProcedure);
|
|
|
|
currentProcedure->graph->getPrivate();
|
|
#if ACCAN_DEBUG
|
|
calls.printControlFlows();
|
|
#endif
|
|
//stage 2: data flow analysis
|
|
FillCFGSets(CGraph);
|
|
//stage 3: fulfilling loop data
|
|
FillPrivates(CGraph);
|
|
|
|
//test: graphvis
|
|
/*std::fstream fs;
|
|
fs.open("graph_old.txt", std::fstream::out);
|
|
fs << CGraph->GetVisualGraph(&calls);
|
|
fs.close();*/
|
|
|
|
#if !__SPF
|
|
delete CGraph;
|
|
#endif
|
|
|
|
if (privateDelayedList)
|
|
delete privateDelayedList;
|
|
privateDelayedList = NULL;
|
|
}
|
|
|
|
CallData::~CallData()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
/*
|
|
for (AnalysedCallsList* l = calls_list; l != NULL;)
|
|
{
|
|
if (!l->isIntrinsic && l->graph)
|
|
{
|
|
if (l->graph->RemoveRef() && !l->graph->IsMain())
|
|
{
|
|
delete l->graph;
|
|
l->graph = NULL;
|
|
}
|
|
}
|
|
AnalysedCallsList *temp = l;
|
|
l = l->next;
|
|
delete temp;
|
|
temp = NULL;
|
|
}*/
|
|
}
|
|
|
|
CommonData::~CommonData()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
for (CommonDataItem* i = list; i != NULL;) {
|
|
for (CommonVarInfo* info = i->info; info != NULL;) {
|
|
CommonVarInfo* t = info;
|
|
info = info->next;
|
|
delete t;
|
|
}
|
|
CommonDataItem* tp = i;
|
|
i = i->next;
|
|
delete tp;
|
|
}
|
|
}
|
|
|
|
ControlFlowGraph::~ControlFlowGraph()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
while (common_def != NULL)
|
|
{
|
|
CommonVarSet* t = common_def;
|
|
common_def = common_def->next;
|
|
delete t;
|
|
}
|
|
while (common_use != NULL)
|
|
{
|
|
CommonVarSet* t = common_use;
|
|
common_use = common_use->next;
|
|
delete t;
|
|
}
|
|
|
|
if (def)
|
|
delete def;
|
|
|
|
if (use)
|
|
delete use;
|
|
|
|
if (!temp && pri)
|
|
delete pri;
|
|
|
|
for (CBasicBlock *bb = first; bb != NULL;)
|
|
{
|
|
CBasicBlock *tmp = bb;
|
|
bb = bb->getLexNext();
|
|
|
|
delete tmp;
|
|
tmp = NULL;
|
|
}
|
|
}
|
|
|
|
CBasicBlock::~CBasicBlock()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
|
|
CommonVarSet* d = getCommonDef();
|
|
while (d != NULL)
|
|
{
|
|
CommonVarSet* t = d;
|
|
d = d->next;
|
|
delete t;
|
|
}
|
|
|
|
d = getCommonUse();
|
|
while (d != NULL)
|
|
{
|
|
CommonVarSet* t = d;
|
|
d = d->next;
|
|
delete t;
|
|
}
|
|
|
|
for (BasicBlockItem* bbi = prev; bbi != NULL;)
|
|
{
|
|
BasicBlockItem *tmp = bbi;
|
|
bbi = bbi->next;
|
|
delete tmp;
|
|
tmp = NULL;
|
|
}
|
|
|
|
for (BasicBlockItem *bbi = succ; bbi != NULL;)
|
|
{
|
|
BasicBlockItem *tmp = bbi;
|
|
bbi = bbi->next;
|
|
delete tmp;
|
|
tmp = NULL;
|
|
}
|
|
|
|
if (def)
|
|
delete def;
|
|
|
|
if (use)
|
|
delete use;
|
|
|
|
if (old_mrd_out)
|
|
delete old_mrd_out;
|
|
|
|
if (old_mrd_in)
|
|
delete old_mrd_in;
|
|
|
|
if (mrd_in)
|
|
delete mrd_in;
|
|
|
|
if (mrd_out)
|
|
delete mrd_out;
|
|
|
|
if (old_lv_out)
|
|
delete old_lv_out;
|
|
|
|
if (old_lv_in)
|
|
delete old_lv_in;
|
|
|
|
if (lv_in)
|
|
delete lv_in;
|
|
|
|
if (lv_out)
|
|
delete lv_out;
|
|
}
|
|
|
|
doLoops::~doLoops()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
for (doLoopItem *it = first; it != NULL; )
|
|
{
|
|
doLoopItem *tmp = it;
|
|
it = it->getNext();
|
|
delete tmp;
|
|
}
|
|
}
|
|
|
|
PrivateDelayedItem::~PrivateDelayedItem()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
if (delay)
|
|
delete delay;
|
|
if (next)
|
|
delete next;
|
|
}
|
|
|
|
VarSet::~VarSet()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
#endif
|
|
for (VarItem* it = list; it != NULL;)
|
|
{
|
|
VarItem* tmp = it;
|
|
it = it->next;
|
|
if (tmp->var)
|
|
if (tmp->var->RemoveReference())
|
|
delete tmp->var;
|
|
delete tmp;
|
|
}
|
|
}
|
|
|
|
CommonVarSet::CommonVarSet(const CommonVarSet& c)
|
|
{
|
|
cvd = c.cvd;
|
|
if (c.next)
|
|
next = new CommonVarSet(*c.next);
|
|
else
|
|
next = NULL;
|
|
|
|
#if __SPF
|
|
addToCollection(__LINE__, __FILE__, this, 22);
|
|
#endif
|
|
}
|
|
|
|
std::string ControlFlowGraph::GetVisualGraph(CallData* calls)
|
|
{
|
|
std::string result;
|
|
result += "digraph ";
|
|
char tmp[512];
|
|
AnalysedCallsList* cd = calls->GetDataForGraph(this);
|
|
//if (cd == NULL || cd->header == NULL)
|
|
sprintf(tmp, "g_%llx", (uintptr_t)this);
|
|
//else
|
|
// sprintf(tmp, "g_%500s", cd->header->symbol());
|
|
result += tmp;
|
|
result += "{ \n";
|
|
for (CBasicBlock* b = this->first; b != NULL; b = b->getLexNext()) {
|
|
if (!b->IsEmptyBlock()) {
|
|
result += '\t' + b->GetGraphVisDescription() + "[shape=box,label=\"";
|
|
result += b->GetGraphVisData() + "\"];\n";
|
|
}
|
|
}
|
|
for (CBasicBlock* b = first; b != NULL; b = b->getLexNext()) {
|
|
if (!b->IsEmptyBlock())
|
|
result += b->GetEdgesForBlock(b->GetGraphVisDescription(), true, "");
|
|
}
|
|
result += '}';
|
|
ResetDrawnStatusForAllItems();
|
|
return result;
|
|
}
|
|
|
|
void ControlFlowGraph::ResetDrawnStatusForAllItems() {
|
|
for (CBasicBlock* b = first; b != NULL; b = b->getLexNext()) {
|
|
for (ControlFlowItem* it = b->getStart(); it != NULL && (it->isLeader() == false || it == b->getStart()); it = it->getNext()) {
|
|
it->ResetDrawnStatus();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string GetConditionWithLineNumber(ControlFlowItem* eit)
|
|
{
|
|
std::string res;
|
|
if (eit->getOriginalStatement()) {
|
|
char tmp[16];
|
|
sprintf(tmp, "%d: ", eit->getOriginalStatement()->lineNumber());
|
|
res = tmp;
|
|
}
|
|
return res + eit->getExpression()->unparse();
|
|
}
|
|
|
|
std::string GetActualCondition(ControlFlowItem** pItem) {
|
|
std::string res = "";
|
|
ControlFlowItem* eit = *pItem;
|
|
while (true)
|
|
{
|
|
if (eit == NULL || eit->getJump() != NULL || eit->getStatement() != NULL)
|
|
{
|
|
if (eit && eit->getJump() != NULL)
|
|
{
|
|
if (eit->getExpression() != NULL)
|
|
{
|
|
*pItem = eit;
|
|
return GetConditionWithLineNumber(eit);
|
|
}
|
|
else
|
|
{
|
|
*pItem = NULL;
|
|
return res;
|
|
}
|
|
break;
|
|
}
|
|
*pItem = NULL;
|
|
return res;
|
|
}
|
|
eit = eit->GetPrev();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::string CBasicBlock::GetEdgesForBlock(std::string name, bool original, std::string modifier)
|
|
{
|
|
std::string result;
|
|
for (BasicBlockItem* it = getSucc(); it != NULL; it = it->next) {
|
|
if (it->drawn)
|
|
continue;
|
|
it->drawn = true;
|
|
char lo = original;
|
|
std::string cond;
|
|
ControlFlowItem* eit = NULL;
|
|
bool pf = false;
|
|
if (it->jmp != NULL) {
|
|
if (it->jmp->getExpression() != NULL) {
|
|
eit = it->jmp;
|
|
cond = GetConditionWithLineNumber(eit);
|
|
}
|
|
else {
|
|
pf = true;
|
|
eit = it->jmp->GetPrev();
|
|
cond = GetActualCondition(&eit);
|
|
}
|
|
}
|
|
if (eit && eit->GetFriend()) {
|
|
lo = false;
|
|
eit = eit->GetFriend();
|
|
}
|
|
if (!it->block->IsEmptyBlock() || cond.length() != 0) {
|
|
if (cond.length() != 0 && eit && !pf){
|
|
char tmp[32];
|
|
sprintf(tmp, "c_%llx", (uintptr_t)eit);
|
|
if (!eit->IsDrawn()) {
|
|
result += '\t';
|
|
result += tmp;
|
|
result += "[shape=diamond,label=\"";
|
|
result += cond;
|
|
result += "\"];\n";
|
|
}
|
|
if (it->cond_value && !pf) {
|
|
result += '\t' + name + "->";
|
|
result += tmp;
|
|
result += modifier;
|
|
result += '\n';
|
|
}
|
|
eit->SetIsDrawn();
|
|
}
|
|
if (cond.length() != 0) {
|
|
if (lo) {
|
|
char tmp[32];
|
|
sprintf(tmp, "c_%llx", (uintptr_t)eit);
|
|
if (!it->block->IsEmptyBlock()) {
|
|
result += '\t';
|
|
result += tmp;
|
|
result += "->" + it->block->GetGraphVisDescription();
|
|
result += "[label=";
|
|
result += (!pf && it->cond_value) ? "T]" : "F]";
|
|
result += ";\n";
|
|
}
|
|
else {
|
|
std::string n = tmp;
|
|
std::string label;
|
|
label += "[label=";
|
|
label += (!pf && it->cond_value) ? "T]" : "F]";
|
|
result += it->block->GetEdgesForBlock(n, original, label);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
result += '\t' + name + " -> " + it->block->GetGraphVisDescription();
|
|
result += modifier;
|
|
result += ";\n";
|
|
}
|
|
|
|
}
|
|
else {
|
|
result += it->block->GetEdgesForBlock(name, original, "");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string CBasicBlock::GetGraphVisDescription()
|
|
{
|
|
if (visname.length() != 0)
|
|
return visname;
|
|
char tmp[16];
|
|
sprintf(tmp, "%d", num);
|
|
visname = tmp;
|
|
return visname;
|
|
}
|
|
|
|
std::string CBasicBlock::GetGraphVisData()
|
|
{
|
|
if (visunparse.length() != 0)
|
|
return visunparse;
|
|
std::string result;
|
|
for (ControlFlowItem* it = start; it != NULL && (it->isLeader() == false || it == start); it = it->getNext()) {
|
|
if (it->getStatement() != NULL) {
|
|
int ln = it->GetLineNumber();
|
|
char tmp[16];
|
|
sprintf(tmp, "%d: ", ln);
|
|
result += tmp;
|
|
result += it->getStatement()->unparse();
|
|
}
|
|
}
|
|
visunparse = result;
|
|
return result;
|
|
}
|
|
|
|
int ControlFlowItem::GetLineNumber()
|
|
{
|
|
if (getStatement() == NULL)
|
|
return 0;
|
|
if (getStatement()->lineNumber() == 0){
|
|
if (getOriginalStatement() == NULL)
|
|
return 0;
|
|
return getOriginalStatement()->lineNumber();
|
|
}
|
|
return getStatement()->lineNumber();
|
|
}
|
|
|
|
bool CBasicBlock::IsEmptyBlock()
|
|
{
|
|
for (ControlFlowItem* it = start; it != NULL && (it->isLeader() == false || it == start); it = it->getNext()) {
|
|
if (!it->IsEmptyCFI())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
AnalysedCallsList* CallData::GetDataForGraph(ControlFlowGraph* s)
|
|
{
|
|
for (AnalysedCallsList* it = calls_list; it != NULL; it = it->next) {
|
|
if (it->graph == s)
|
|
return it;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ControlFlowGraph* GetControlFlowGraphWithCalls(bool main, SgStatement* start, CallData* calls, CommonData* commons)
|
|
{
|
|
if (start == NULL)
|
|
{
|
|
//is_correct = "no body for call found";
|
|
return NULL;
|
|
}
|
|
|
|
ControlFlowGraph *cfgRet = NULL;
|
|
/*
|
|
#if __SPF
|
|
auto itF = CFG_cache.find(start);
|
|
if (itF != CFG_cache.end())
|
|
{
|
|
calls = std::get<1>(itF->second);
|
|
commons = std::get<2>(itF->second);
|
|
return std::get<0>(itF->second);
|
|
}
|
|
#endif*/
|
|
doLoops l;
|
|
ControlFlowItem *funcGraph = getControlFlowList(start, start->lastNodeOfStmt(), NULL, NULL, &l, calls, commons);
|
|
fillLabelJumps(funcGraph);
|
|
setLeaders(funcGraph);
|
|
|
|
|
|
cfgRet = new ControlFlowGraph(false, main, funcGraph, NULL);
|
|
//CFG_cache[start] = std::make_tuple(cfgRet, calls, commons);
|
|
return cfgRet;
|
|
}
|
|
|
|
void FillCFGSets(ControlFlowGraph* graph)
|
|
{
|
|
graph->privateAnalyzer();
|
|
}
|
|
|
|
static void ClearMemoryAfterDelay(ActualDelayedData* d)
|
|
{
|
|
while (d != NULL) {
|
|
CommonVarSet* cd = d->commons;
|
|
while (cd != NULL) {
|
|
CommonVarSet* t = cd;
|
|
cd = cd->next;
|
|
delete t;
|
|
}
|
|
delete d->buse;
|
|
ActualDelayedData* tmp = d;
|
|
d = d->next;
|
|
delete tmp;
|
|
}
|
|
}
|
|
|
|
static void FillPrivates(ControlFlowGraph* graph)
|
|
{
|
|
ActualDelayedData* d = graph->ProcessDelayedPrivates(pCommons, mainProcedure, NULL, NULL, false, -1);
|
|
ClearMemoryAfterDelay(d);
|
|
if (privateDelayedList)
|
|
privateDelayedList->PrintWarnings();
|
|
}
|
|
|
|
ActualDelayedData* CBasicBlock::GetDelayedDataForCall(CallAnalysisLog* log)
|
|
{
|
|
for (ControlFlowItem* it = start; it != NULL && (!it->isLeader() || it == start); it = it->getNext())
|
|
{
|
|
AnalysedCallsList* c = it->getCall();
|
|
void* cf = it->getFunctionCall();
|
|
bool isFun = true;
|
|
if (!cf) {
|
|
cf = it->getStatement();
|
|
isFun = false;
|
|
}
|
|
if (c != NULL && c != (AnalysedCallsList*)(-1) && c != (AnalysedCallsList*)(-2) && c->graph != NULL)
|
|
return c->graph->ProcessDelayedPrivates(pCommons, c, log, cf, isFun, it->getProc()->file_id);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void PrivateDelayedItem::MoveFromPrivateToLastPrivate(CVarEntryInfo* var)
|
|
{
|
|
VarItem* el = detected->belongs(var);
|
|
if (el) {
|
|
eVariableType storedType = el->var->GetVarType();
|
|
detected->remove(el->var);
|
|
lp->addToSet(var, NULL);
|
|
}
|
|
}
|
|
|
|
void ActualDelayedData::RemoveVarFromCommonList(CommonVarSet* c)
|
|
{
|
|
if (commons == NULL || c == NULL)
|
|
return;
|
|
if (c == commons)
|
|
{
|
|
commons = commons->next;
|
|
delete c;
|
|
return;
|
|
}
|
|
CommonVarSet* prev = c;
|
|
for (CommonVarSet* cur = c->next; cur != NULL; cur = cur->next)
|
|
{
|
|
if (cur == c)
|
|
{
|
|
prev->next = c->next;
|
|
delete c;
|
|
return;
|
|
}
|
|
else
|
|
prev = cur;
|
|
}
|
|
}
|
|
|
|
void ActualDelayedData::MoveVarFromPrivateToLastPrivate(CVarEntryInfo* var, CommonVarSet* c, VarSet* vs)
|
|
{
|
|
original->MoveFromPrivateToLastPrivate(var);
|
|
RemoveVarFromCommonList(c);
|
|
if (vs)
|
|
{
|
|
if (vs->belongs(var))
|
|
vs->remove(var);
|
|
}
|
|
}
|
|
|
|
int IsThisVariableAParameterOfSubroutine(AnalysedCallsList* lst, SgSymbol* s)
|
|
{
|
|
if (!lst->header)
|
|
return -1;
|
|
int stored = SwitchFile(lst->file_id);
|
|
SgProcHedrStmt* h = isSgProcHedrStmt(lst->header);
|
|
if (!h)
|
|
return -1;
|
|
for (int i = 0; i < h->numberOfParameters(); i++) {
|
|
SgSymbol* par = h->parameter(i);
|
|
if (par == s) {
|
|
SwitchFile(stored);
|
|
return i;
|
|
}
|
|
}
|
|
SwitchFile(stored);
|
|
return -1;
|
|
}
|
|
|
|
ActualDelayedData* ControlFlowGraph::ProcessDelayedPrivates(CommonData* commons, AnalysedCallsList* call, CallAnalysisLog* log, void* c, bool isFun, int file_id)
|
|
{
|
|
for (CallAnalysisLog* i = log; i != NULL; i = i->prev) {
|
|
if (i->el == call)
|
|
{
|
|
//TODO: add name of common
|
|
#if __SPF
|
|
const wchar_t* rus = R158;
|
|
Warning("Recursion is not analyzed for privates in common blocks '%s'", rus, "TODO!", PRIVATE_ANALYSIS_NO_RECURSION_ANALYSIS, call->header);
|
|
#else
|
|
Warning("Recursion is not analyzed for privates in common blocks '%s'", "TODO!", PRIVATE_ANALYSIS_NO_RECURSION_ANALYSIS, call->header);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
}
|
|
CallAnalysisLog* nl = new CallAnalysisLog();
|
|
nl->el = call;
|
|
nl->prev = log;
|
|
if (log == NULL)
|
|
nl->depth = 0;
|
|
else
|
|
nl->depth = log->depth + 1;
|
|
log = nl;
|
|
ActualDelayedData* my = NULL;
|
|
for (CBasicBlock* bb = first; bb != NULL; bb = bb->getLexNext()) {
|
|
if (bb->containsParloopStart()) {
|
|
if (bb->GetDelayedData()) {
|
|
ActualDelayedData* data = new ActualDelayedData();
|
|
data->original = bb->GetDelayedData();
|
|
data->commons = commons->GetCommonsForVarSet(data->original->getDetected(), call);
|
|
VarSet* bu = new VarSet();
|
|
bu->unite(data->original->getDelayed(), false);
|
|
VarSet* tbu = new VarSet();
|
|
while (!bu->isEmpty()) {
|
|
if (IS_BY_USE(bu->getFirst()->var->GetSymbol()))
|
|
tbu->addToSet(bu->getFirst()->var, NULL);
|
|
else {
|
|
CVarEntryInfo* old = bu->getFirst()->var;
|
|
int arg_id = IsThisVariableAParameterOfSubroutine(call, bu->getFirst()->var->GetSymbol());
|
|
if (arg_id != -1 && c != NULL) {
|
|
int stored = SwitchFile(file_id);
|
|
SgExpression* exp = GetProcedureArgument(isFun, c, arg_id);
|
|
if (isSgVarRefExp(exp) || isSgArrayRefExp(exp)) {
|
|
SgSymbol* sym = exp->symbol();
|
|
CVarEntryInfo* v;
|
|
if (isSgVarRefExp(exp)) {
|
|
v = new CScalarVarEntryInfo(sym);
|
|
}
|
|
else {
|
|
v = old->Clone(sym);
|
|
}
|
|
tbu->addToSet(v, NULL, old);
|
|
}
|
|
SwitchFile(stored);
|
|
|
|
}
|
|
}
|
|
bu->remove(bu->getFirst()->var);
|
|
}
|
|
data->buse = tbu;
|
|
delete bu;
|
|
data->next = my;
|
|
data->call = call;
|
|
my = data;
|
|
}
|
|
}
|
|
ActualDelayedData* calldata = bb->GetDelayedDataForCall(log);
|
|
while (calldata != NULL) {
|
|
CommonVarSet* nxt = NULL;
|
|
for (CommonVarSet* t = calldata->commons; t != NULL; t = nxt) {
|
|
nxt = t->next;
|
|
CommonVarInfo* cvd = t->cvd;
|
|
CommonDataItem* d = commons->IsThisCommonUsedInProcedure(cvd->parent, call);
|
|
if (!d || commons->CanHaveNonScalarVars(d))
|
|
continue;
|
|
CommonVarInfo* j = cvd->parent->info;
|
|
CommonVarInfo* i = d->info;
|
|
while (j != cvd) {
|
|
j = j->next;
|
|
if (i)
|
|
i = i->next;
|
|
}
|
|
if (!i)
|
|
continue;
|
|
CVarEntryInfo* var = i->var;
|
|
if (bb->getLexNext()->getLiveIn()->belongs(var->GetSymbol()) && calldata->original->getDelayed()->belongs(cvd->var)) {
|
|
calldata->MoveVarFromPrivateToLastPrivate(cvd->var, t, NULL);
|
|
}
|
|
if (bb->IsVarDefinedAfterThisBlock(var, false)) {
|
|
calldata->RemoveVarFromCommonList(t);
|
|
}
|
|
|
|
}
|
|
if (log->el->header == calldata->call->header) {
|
|
VarSet* pr = new VarSet();
|
|
pr->unite(calldata->original->getDelayed(), false);
|
|
pr->intersect(bb->getLexNext()->getLiveIn(), false, true);
|
|
for (VarItem* exp = pr->getFirst(); exp != NULL; pr->getFirst()) {
|
|
calldata->MoveVarFromPrivateToLastPrivate(exp->var, NULL, NULL);
|
|
pr->remove(exp->var);
|
|
}
|
|
delete pr;
|
|
}
|
|
VarSet* tmp_use = new VarSet();
|
|
tmp_use->unite(calldata->buse, false);
|
|
while (!tmp_use->isEmpty()) {
|
|
VarItem* v = tmp_use->getFirst();
|
|
CVarEntryInfo* tmp = v->var->Clone(OriginalSymbol(v->var->GetSymbol()));
|
|
if (bb->getLexNext()->getLiveIn()->belongs(tmp->GetSymbol(), true)) {
|
|
calldata->MoveVarFromPrivateToLastPrivate(v->ov ? v->ov : v->var, NULL, calldata->buse);
|
|
}
|
|
if (bb->IsVarDefinedAfterThisBlock(v->var, true)) {
|
|
calldata->buse->remove(v->ov ? v->ov : v->var);
|
|
}
|
|
delete tmp;
|
|
tmp_use->remove(v->var);
|
|
}
|
|
delete tmp_use;
|
|
ActualDelayedData* tmp = calldata->next;
|
|
calldata->next = my;
|
|
my = calldata;
|
|
calldata = tmp;
|
|
}
|
|
}
|
|
nl = log;
|
|
log = log->prev;
|
|
|
|
delete nl;
|
|
return my;
|
|
}
|
|
|
|
extern graph_node* node_list;
|
|
void Private_Vars_Function_Analyzer(SgStatement* start);
|
|
|
|
void Private_Vars_Project_Analyzer()
|
|
{
|
|
graph_node* node = node_list;
|
|
while (node) {
|
|
if (node->st_header) {
|
|
int stored_file_id = SwitchFile(node->file_id);
|
|
Private_Vars_Function_Analyzer(node->st_header);
|
|
SwitchFile(stored_file_id);
|
|
}
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
// CALL function for PRIVATE analyzing
|
|
void Private_Vars_Function_Analyzer(SgStatement* start)
|
|
{
|
|
//temporary state
|
|
#ifndef __SPF
|
|
if (!options.isOn(PRIVATE_ANALYSIS)){
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (start->variant() == PROG_HEDR) {
|
|
Private_Vars_Analyzer(start);
|
|
}
|
|
/*
|
|
ControlFlowItem* funcGraph = getControlFlowList(start, start->lastNodeOfStmt(), NULL, NULL, new doLoops());
|
|
fillLabelJumps(funcGraph);
|
|
setLeaders(funcGraph);
|
|
#if ACCAN_DEBUG
|
|
printControlFlowList(funcGraph);
|
|
#endif
|
|
ControlFlowItem* p = funcGraph;
|
|
ControlFlowItem* pl_start = NULL;
|
|
ControlFlowItem* pl_end = NULL;
|
|
ControlFlowGraph* graph = new ControlFlowGraph(funcGraph, NULL);
|
|
graph->privateAnalyzer();
|
|
*/
|
|
}
|
|
/*
|
|
// CALL function for PRIVATE analyzing
|
|
void Private_Vars_Analyzer(SgStatement *firstSt, SgStatement *lastSt)
|
|
{
|
|
// temporary state
|
|
//return;
|
|
SgExpression* par_des = firstSt->expr(2);
|
|
SgSymbol* l;
|
|
SgForStmt* chk;
|
|
int correct = 1;
|
|
firstSt = firstSt->lexNext();
|
|
while (correct && (par_des != NULL) && (par_des->lhs() != NULL) && ((l = par_des->lhs()->symbol()) != NULL)){
|
|
if (firstSt->variant() == FOR_NODE){
|
|
chk = isSgForStmt(firstSt);
|
|
if (chk->symbol() != l)
|
|
correct = 0;
|
|
firstSt = firstSt->lexNext();
|
|
par_des = par_des->rhs();
|
|
}
|
|
else{
|
|
correct = 0;
|
|
}
|
|
}
|
|
if (correct){
|
|
doLoops* loops = new doLoops();
|
|
ControlFlowItem* cfList = getControlFlowList(firstSt, lastSt, NULL, NULL, loops);
|
|
fillLabelJumps(cfList);
|
|
setLeaders(cfList);
|
|
#if ACCAN_DEBUG
|
|
printControlFlowList(cfList);
|
|
#endif
|
|
VarSet* priv = ControlFlowGraph(cfList, NULL).getPrivate();
|
|
#if ACCAN_DEBUG
|
|
priv->print();
|
|
#endif
|
|
clearList(cfList);
|
|
}
|
|
}
|
|
*/
|
|
|
|
static void fillLabelJumps(ControlFlowItem* cfList)
|
|
{
|
|
if (cfList != NULL){
|
|
ControlFlowItem* temp = cfList;
|
|
ControlFlowItem* temp2;
|
|
unsigned int label_no = 0;
|
|
while (temp != NULL){
|
|
if (temp->getLabel() != NULL)
|
|
label_no++;
|
|
temp = temp->getNext();
|
|
}
|
|
LabelCFI* table = new LabelCFI[label_no + 1];
|
|
unsigned int li = 0;
|
|
for (temp = cfList; temp != NULL; temp = temp->getNext()){
|
|
SgLabel* label;
|
|
if ((label = temp->getLabel()) != NULL){
|
|
table[li].item = temp;
|
|
table[li++].l = label->id();
|
|
}
|
|
temp2 = temp;
|
|
}
|
|
temp = new ControlFlowItem(currentProcedure);
|
|
temp2->AddNextItem(temp);
|
|
table[label_no].item = temp2;
|
|
table[label_no].l = -1;
|
|
for (temp = cfList; temp != NULL; temp = temp->getNext()){
|
|
SgLabel* jump = temp->getLabelJump();
|
|
int l;
|
|
if (jump != NULL){
|
|
l = jump->id();
|
|
for (unsigned int i = 0; i < label_no + 1; i++){
|
|
if (table[i].l == l || i == label_no){
|
|
temp->initJump(table[i].item);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete[] table;
|
|
}
|
|
}
|
|
|
|
static void setLeaders(ControlFlowItem* cfList)
|
|
{
|
|
if (cfList != NULL)
|
|
cfList->setLeader();
|
|
while (cfList != NULL)
|
|
{
|
|
if (cfList->getJump() != NULL)
|
|
{
|
|
cfList->getJump()->setLeader();
|
|
if (cfList->getNext() != NULL)
|
|
cfList->getNext()->setLeader();
|
|
}
|
|
if (cfList->getCall() != NULL)
|
|
{
|
|
if (cfList->getNext() != NULL)
|
|
cfList->getNext()->setLeader();
|
|
}
|
|
cfList = cfList->getNext();
|
|
}
|
|
}
|
|
|
|
static void clearList(ControlFlowItem *list)
|
|
{
|
|
if (list != NULL)
|
|
{
|
|
if (list->getNext() != NULL)
|
|
clearList(list->getNext());
|
|
|
|
delete list;
|
|
}
|
|
}
|
|
|
|
static ControlFlowItem* ifItem(SgStatement* stmt, ControlFlowItem* empty, SgStatement** lastAnStmt, doLoops* loops, bool ins, CallData* calls, CommonData* commons)
|
|
{
|
|
if (stmt == NULL)
|
|
return empty;
|
|
SgIfStmt* cond;
|
|
if (stmt->variant() == ELSEIF_NODE)
|
|
cond = (SgIfStmt*)stmt;
|
|
if (stmt->variant() == ELSEIF_NODE || (!ins && (cond = isSgIfStmt(stmt)) != NULL))
|
|
{
|
|
SgExpression* c = &(SgNotOp((cond->conditional()->copy())));
|
|
ControlFlowItem *n, *j;
|
|
ControlFlowItem* last;
|
|
if ((n = getControlFlowList(cond->trueBody(), NULL, &last, lastAnStmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
j = ifItem(cond->falseBody(), empty, lastAnStmt, loops, cond->falseBody() != NULL ? cond->falseBody()->variant() == IF_NODE : false, calls, commons);
|
|
ControlFlowItem* gotoEmpty = new ControlFlowItem(NULL, empty, j, NULL, currentProcedure);
|
|
if (last != NULL)
|
|
last->AddNextItem(gotoEmpty);
|
|
else
|
|
n = gotoEmpty;
|
|
ControlFlowItem* tn = new ControlFlowItem(c, j, n, stmt->label(), currentProcedure);
|
|
tn->setOriginalStatement(stmt);
|
|
return tn;
|
|
}
|
|
else
|
|
{
|
|
ControlFlowItem* last;
|
|
ControlFlowItem* ret;
|
|
if ((ret = getControlFlowList(stmt, NULL, &last, lastAnStmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
last->AddNextItem(empty);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
static ControlFlowItem* switchItem(SgStatement* stmt, ControlFlowItem* empty, SgStatement** lastAnStmt, doLoops* loops, CallData* calls, CommonData* commons)
|
|
{
|
|
SgSwitchStmt* sw = isSgSwitchStmt(stmt);
|
|
SgExpression* sw_cond = (sw->selector());
|
|
stmt = stmt->lexNext();
|
|
*lastAnStmt = stmt;
|
|
ControlFlowItem* last_sw = NULL;
|
|
ControlFlowItem* first = NULL;
|
|
bool is_def_last = false;
|
|
SgStatement* not_def_last;
|
|
while (stmt->variant() == CASE_NODE || stmt->variant() == DEFAULT_NODE)
|
|
{
|
|
if (stmt->variant() == DEFAULT_NODE){
|
|
while (stmt->variant() != CONTROL_END && stmt->variant() != CASE_NODE)
|
|
stmt = stmt->lexNext();
|
|
if (stmt->variant() == CONTROL_END)
|
|
stmt = stmt->lexNext();
|
|
is_def_last = true;
|
|
continue;
|
|
}
|
|
SgExpression* c = ((SgCaseOptionStmt*)stmt)->caseRange(0);
|
|
SgExpression *lhs = NULL;
|
|
SgExpression *rhs = NULL;
|
|
if (c->variant() == DDOT){
|
|
lhs = c->lhs();
|
|
rhs = c->rhs();
|
|
if (rhs == NULL)
|
|
c = &(*lhs <= *sw_cond);
|
|
else if (lhs == NULL)
|
|
c = &(*sw_cond <= *rhs);
|
|
else
|
|
c = &(*lhs <= *sw_cond && *sw_cond <= *rhs);
|
|
}
|
|
else
|
|
c = &SgNeqOp(*sw_cond, *c);
|
|
ControlFlowItem *n, *j;
|
|
ControlFlowItem* last;
|
|
if ((n = getControlFlowList(stmt->lexNext(), NULL, &last, lastAnStmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
j = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* gotoEmpty = new ControlFlowItem(NULL, empty, j, NULL, currentProcedure);
|
|
if (last != NULL)
|
|
last->AddNextItem(gotoEmpty);
|
|
else
|
|
n = gotoEmpty;
|
|
ControlFlowItem* cond = new ControlFlowItem(c, j, n, stmt->label(), currentProcedure);
|
|
cond->setOriginalStatement(stmt);
|
|
if (last_sw == NULL)
|
|
first = cond;
|
|
else
|
|
last_sw->AddNextItem(cond);
|
|
last_sw = j;
|
|
is_def_last = false;
|
|
not_def_last = *lastAnStmt;
|
|
stmt = *lastAnStmt;
|
|
}
|
|
SgStatement* def = sw->defOption();
|
|
if (def != NULL){
|
|
ControlFlowItem* last;
|
|
ControlFlowItem* n;
|
|
if ((n = getControlFlowList(def->lexNext(), NULL, &last, lastAnStmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
if (last != NULL)
|
|
last->AddNextItem(empty);
|
|
if (last_sw == NULL)
|
|
first = n;
|
|
else
|
|
last_sw->AddNextItem(n);
|
|
last_sw = last;
|
|
}
|
|
last_sw->AddNextItem(empty);
|
|
if (!is_def_last)
|
|
*lastAnStmt = not_def_last;
|
|
return first;
|
|
}
|
|
|
|
static ControlFlowItem* getControlFlowList(SgStatement *firstSt, SgStatement *lastSt, ControlFlowItem **last, SgStatement **lastAnStmt, doLoops* loops, CallData* calls, CommonData* commons)
|
|
{
|
|
ControlFlowItem *list = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem *cur = list;
|
|
ControlFlowItem *pred = list;
|
|
SgStatement *stmt;
|
|
for (stmt = firstSt; (
|
|
stmt != lastSt
|
|
&& stmt->variant() != CONTAINS_STMT
|
|
&& (lastSt != NULL || stmt->variant() != ELSEIF_NODE)
|
|
&& (lastSt != NULL || stmt->variant() != CASE_NODE)
|
|
&& (lastSt != NULL || stmt->variant() != DEFAULT_NODE));
|
|
stmt = stmt->lexNext())
|
|
{
|
|
if (stmt->variant() == CONTROL_END)
|
|
{
|
|
if (isSgExecutableStatement(stmt))
|
|
break;
|
|
}
|
|
|
|
cur = processOneStatement(&stmt, &pred, &list, cur, loops, calls, commons);
|
|
if (cur == NULL)
|
|
{
|
|
clearList(list);
|
|
return NULL;
|
|
}
|
|
}
|
|
if (cur == NULL){
|
|
cur = list = new ControlFlowItem(currentProcedure);
|
|
}
|
|
if (last != NULL)
|
|
*last = cur;
|
|
if (lastAnStmt != NULL)
|
|
*lastAnStmt = stmt;
|
|
return list;
|
|
}
|
|
|
|
AnalysedCallsList* CallData::IsHeaderInList(SgStatement* header)
|
|
{
|
|
if (header == NULL)
|
|
return NULL;
|
|
AnalysedCallsList* p = calls_list;
|
|
while (p != NULL) {
|
|
if (p->header == header)
|
|
return p;
|
|
p = p->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CallData::AssociateGraphWithHeader(SgStatement* st, ControlFlowGraph* gr)
|
|
{
|
|
AnalysedCallsList* l = calls_list;
|
|
while (l != NULL) {
|
|
if (l->header == st) {
|
|
if (gr == l->graph && gr != NULL)
|
|
gr->AddRef();
|
|
l->graph = gr;
|
|
return;
|
|
}
|
|
l = l->next;
|
|
}
|
|
delete gr;
|
|
}
|
|
|
|
AnalysedCallsList* CallData::AddHeader(SgStatement* st, bool isFun, SgSymbol* name, int fid)
|
|
{
|
|
//test
|
|
bool add_intr = IsAnIntrinsicSubroutine(name->identifier()) != NULL;
|
|
AnalysedCallsList* l = new AnalysedCallsList(st, (isIntrinsicFunctionNameACC(name->identifier()) || add_intr) && !IsUserFunctionACC(name), IsPureProcedureACC(name), isFun, name->identifier(), fid);
|
|
l->next = calls_list;
|
|
calls_list = l;
|
|
return l;
|
|
}
|
|
|
|
extern int isStatementFunction(SgSymbol *s);
|
|
|
|
AnalysedCallsList* CallData::getLinkToCall(SgExpression* e, SgStatement* s, CommonData* commons)
|
|
{
|
|
SgStatement* header = NULL;
|
|
SgSymbol* name;
|
|
bool isFun;
|
|
graph_node* g = NULL;
|
|
if (e == NULL) {
|
|
//s - procedure call
|
|
SgCallStmt* f = isSgCallStmt(s);
|
|
SgSymbol* fdaf = f->name();
|
|
if (ATTR_NODE(f->name()) != NULL)
|
|
g = GRAPHNODE(f->name());
|
|
if (g == NULL) {
|
|
|
|
is_correct = "no header for procedure";
|
|
failed_proc_name = f->name()->identifier();
|
|
return (AnalysedCallsList*)(-1);
|
|
|
|
}
|
|
if (g)
|
|
header = isSgProcHedrStmt(g->st_header);
|
|
name = f->name();
|
|
isFun = false;
|
|
//intr = isIntrinsicFunctionNameACC(f->name()->identifier()) && !IsUserFunctionACC(f->name());
|
|
//IsPureProcedureACC(f->name());
|
|
}
|
|
else {
|
|
//e - function call
|
|
SgFunctionCallExp* f = isSgFunctionCallExp(e);
|
|
if (isStatementFunction(f->funName()))
|
|
return (AnalysedCallsList*)(-2);
|
|
if (ATTR_NODE(f->funName()) != NULL)
|
|
g = GRAPHNODE(f->funName());
|
|
if (g == NULL) {
|
|
is_correct = "no header for function";
|
|
failed_proc_name = f->funName()->identifier();
|
|
return (AnalysedCallsList*)(-1);
|
|
}
|
|
header = isSgFuncHedrStmt(g->st_header);
|
|
name = f->funName();
|
|
isFun = true;
|
|
}
|
|
AnalysedCallsList* p;
|
|
if ((p = IsHeaderInList(header))) {
|
|
recursion_flag = recursion_flag || p->graph != NULL;
|
|
return p;
|
|
}
|
|
AnalysedCallsList* prev = currentProcedure;
|
|
currentProcedure = p = AddHeader(header, isFun, name, g->file_id);
|
|
if (!p->isIntrinsic) {
|
|
int stored = SwitchFile(g->file_id);
|
|
|
|
ControlFlowGraph* graph = GetControlFlowGraphWithCalls(false, header, this, commons);
|
|
//if (graph == NULL)
|
|
//failed_proc_name = name->identifier();
|
|
|
|
SwitchFile(stored);
|
|
|
|
AssociateGraphWithHeader(header, graph);
|
|
commons->MarkEndOfCommon(p);
|
|
}
|
|
currentProcedure = prev;
|
|
return p;
|
|
}
|
|
|
|
static ControlFlowItem* GetFuncCallsForExpr(SgExpression* e, CallData* calls, ControlFlowItem** last, CommonData* commons, SgStatement* os)
|
|
{
|
|
if (e == NULL) {
|
|
*last = NULL;
|
|
return NULL;
|
|
}
|
|
SgFunctionCallExp* f = isSgFunctionCallExp(e);
|
|
if (f) {
|
|
ControlFlowItem* head = new ControlFlowItem(NULL, NULL, currentProcedure, calls->getLinkToCall(e, NULL, commons));
|
|
head->setOriginalStatement(os);
|
|
ControlFlowItem* curl = head;
|
|
head->setFunctionCall(f);
|
|
ControlFlowItem* l1, *l2;
|
|
ControlFlowItem* tail1 = GetFuncCallsForExpr(e->lhs(), calls, &l1, commons, os);
|
|
ControlFlowItem* tail2 = GetFuncCallsForExpr(e->rhs(), calls, &l2, commons, os);
|
|
*last = head;
|
|
if (tail2 != NULL) {
|
|
l2->AddNextItem(head);
|
|
head = tail2;
|
|
}
|
|
if (tail1 != NULL) {
|
|
l1->AddNextItem(head);
|
|
head = tail1;
|
|
}
|
|
|
|
return head;
|
|
}
|
|
f = isSgFunctionCallExp(e->lhs());
|
|
if (f) {
|
|
ControlFlowItem* head = new ControlFlowItem(NULL, NULL, currentProcedure, calls->getLinkToCall(e->lhs(), NULL, commons));
|
|
head->setOriginalStatement(os);
|
|
head->setFunctionCall(f);
|
|
ControlFlowItem* l1, *l2, *l3;
|
|
ControlFlowItem* tail1 = GetFuncCallsForExpr(e->lhs()->lhs(), calls, &l1, commons, os);
|
|
ControlFlowItem* tail2 = GetFuncCallsForExpr(e->lhs()->rhs(), calls, &l2, commons, os);
|
|
ControlFlowItem* tail3 = GetFuncCallsForExpr(e->rhs(), calls, &l3, commons, os);
|
|
*last = head;
|
|
if (tail2 != NULL) {
|
|
l2->AddNextItem(head);
|
|
head = tail2;
|
|
}
|
|
if (tail1 != NULL) {
|
|
l1->AddNextItem(head);
|
|
head = tail1;
|
|
}
|
|
if (tail3 != NULL) {
|
|
(*last)->AddNextItem(tail3);
|
|
*last = l3;
|
|
}
|
|
return head;
|
|
}
|
|
return GetFuncCallsForExpr(e->rhs(), calls, last, commons, os);
|
|
}
|
|
|
|
static ControlFlowItem* AddFunctionCalls(SgStatement* st, CallData* calls, ControlFlowItem** last, CommonData* commons)
|
|
{
|
|
ControlFlowItem* retv = GetFuncCallsForExpr(st->expr(0), calls, last, commons, st);
|
|
ControlFlowItem* l2 = NULL;
|
|
ControlFlowItem* second = GetFuncCallsForExpr(st->expr(1), calls, &l2, commons, st);
|
|
if (retv == NULL) {
|
|
retv = second;
|
|
*last = l2;
|
|
}
|
|
else if (second != NULL) {
|
|
(*last)->AddNextItem(second);
|
|
*last = l2;
|
|
}
|
|
ControlFlowItem* l3 = NULL;
|
|
ControlFlowItem* third = GetFuncCallsForExpr(st->expr(2), calls, &l3, commons, st);
|
|
if (retv == NULL) {
|
|
retv = third;
|
|
*last = l3;
|
|
}
|
|
else if (third != NULL) {
|
|
(*last)->AddNextItem(third);
|
|
*last = l3;
|
|
}
|
|
return retv;
|
|
}
|
|
|
|
void DoLoopDataList::AddLoop(int file_id, SgStatement* st, SgExpression* l, SgExpression* r, SgExpression* step, SgSymbol* lv)
|
|
{
|
|
DoLoopDataItem* nt = new DoLoopDataItem();
|
|
nt->file_id = file_id;
|
|
nt->statement = st;
|
|
nt->l = l;
|
|
nt->r = r;
|
|
nt->st = step;
|
|
nt->loop_var = lv;
|
|
nt->next = list;
|
|
list = nt;
|
|
}
|
|
|
|
DoLoopDataList::~DoLoopDataList()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
return;
|
|
#endif
|
|
while (list != NULL) {
|
|
DoLoopDataItem* t = list->next;
|
|
delete list;
|
|
list = t;
|
|
}
|
|
}
|
|
|
|
static ControlFlowItem* processOneStatement(SgStatement** stmt, ControlFlowItem** pred, ControlFlowItem **list, ControlFlowItem* oldcur, doLoops* loops, CallData* calls, CommonData* commons)
|
|
{
|
|
ControlFlowItem* lastf;
|
|
ControlFlowItem* funcs = AddFunctionCalls(*stmt, calls, &lastf, commons);
|
|
if (funcs != NULL) {
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(funcs);
|
|
else
|
|
*list = funcs;
|
|
*pred = lastf;
|
|
}
|
|
|
|
switch ((*stmt)->variant())
|
|
{
|
|
case IF_NODE:
|
|
{
|
|
ControlFlowItem* emptyAfterIf = new ControlFlowItem(currentProcedure); //empty item to avoid second pass
|
|
/*
|
|
if ((*stmt)->hasLabel()){
|
|
ControlFlowItem* emptyBeforeIf = new ControlFlowItem();
|
|
emptyBeforeIf->setLabel((*stmt)->label());
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(emptyBeforeIf);
|
|
else
|
|
*list = emptyBeforeIf;
|
|
*pred = emptyBeforeIf;
|
|
}
|
|
*/
|
|
ControlFlowItem* cur = ifItem(*stmt, emptyAfterIf, stmt, loops, false, calls, commons);
|
|
emptyAfterIf->setLabel((*stmt)->label());
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = emptyAfterIf);
|
|
}
|
|
case ASSIGN_STAT:
|
|
case POINTER_ASSIGN_STAT:
|
|
case PROC_STAT:
|
|
case PRINT_STAT:
|
|
case READ_STAT:
|
|
case WRITE_STAT:
|
|
case ALLOCATE_STMT:
|
|
case DEALLOCATE_STMT:
|
|
{
|
|
ControlFlowItem* cur = new ControlFlowItem(*stmt, NULL, currentProcedure, (*stmt)->variant() == PROC_STAT ? calls->getLinkToCall(NULL, *stmt, commons) : NULL);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = loops->checkStatementForLoopEnding(cur->getLabel() ? cur->getLabel()->id() : -1, cur));
|
|
}
|
|
case LOGIF_NODE:
|
|
{
|
|
ControlFlowItem* emptyAfterIf = new ControlFlowItem(currentProcedure); //empty item to avoid second pass
|
|
SgLogIfStmt* cond = isSgLogIfStmt(*stmt);
|
|
SgLabel* lbl = (*stmt)->label();
|
|
SgExpression* c = &(SgNotOp((cond->conditional()->copy())));
|
|
ControlFlowItem* cur = new ControlFlowItem(c, emptyAfterIf, NULL, (*stmt)->label(), currentProcedure);
|
|
cur->setOriginalStatement(*stmt);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
*stmt = (*stmt)->lexNext();
|
|
ControlFlowItem* body;
|
|
if ((body = processOneStatement(stmt, &cur, list, cur, loops, calls, commons)) == NULL){
|
|
return NULL;
|
|
}
|
|
body->AddNextItem(emptyAfterIf);
|
|
return (*pred = loops->checkStatementForLoopEnding(lbl ? lbl->id() : -1, emptyAfterIf));
|
|
}
|
|
case WHILE_NODE:
|
|
{
|
|
SgWhileStmt* cond = isSgWhileStmt(*stmt);
|
|
bool isEndDo = (*stmt)->lastNodeOfStmt()->variant() == CONTROL_END;
|
|
SgExpression* c;
|
|
if (cond->conditional())
|
|
c = &(SgNotOp((cond->conditional()->copy())));
|
|
else
|
|
c = new SgValueExp(1);
|
|
ControlFlowItem* emptyAfterWhile = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* emptyBeforeBody = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* cur = new ControlFlowItem(c, emptyAfterWhile, emptyBeforeBody, (*stmt)->label(), currentProcedure);
|
|
cur->setOriginalStatement(cond);
|
|
ControlFlowItem* gotoStart = new ControlFlowItem(NULL, cur, emptyAfterWhile, NULL, currentProcedure);
|
|
ControlFlowItem* emptyBefore = new ControlFlowItem(NULL, (ControlFlowItem*)NULL, cur, cond->label(), currentProcedure);
|
|
SgVarRefExp* doName = (isSgVarRefExp((*stmt)->expr(2)));
|
|
int lbl = -1;
|
|
if (!isEndDo){
|
|
SgStatement* end = lastStmtOfDoACC(cond);
|
|
if (end->controlParent() && end->controlParent()->variant() == LOGIF_NODE)
|
|
lbl = end->controlParent()->label()->id();
|
|
else
|
|
lbl = end->label()->id();
|
|
}
|
|
loops->addLoop(lbl, doName ? doName->symbol() : NULL, gotoStart, emptyAfterWhile);
|
|
ControlFlowItem* n, *last;
|
|
if (isEndDo){
|
|
if ((n = getControlFlowList((*stmt)->lexNext(), NULL, &last, stmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
emptyBeforeBody->AddNextItem(n);
|
|
loops->endLoop(last);
|
|
}
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(emptyBefore);
|
|
else
|
|
*list = emptyBefore;
|
|
if (isEndDo)
|
|
return (*pred = emptyAfterWhile);
|
|
return (*pred = emptyBeforeBody);
|
|
}
|
|
case FOR_NODE:
|
|
{
|
|
SgForStmt* fst = isSgForStmt(*stmt);
|
|
#if __SPF
|
|
SgStatement *p = NULL;
|
|
for (int i = 0; i < fst->numberOfAttributes(); ++i)
|
|
{
|
|
if (fst->attributeType(i) == SPF_ANALYSIS_DIR)
|
|
{
|
|
p = (SgStatement *)(fst->getAttribute(i)->getAttributeData());
|
|
break;
|
|
}
|
|
}
|
|
bool isParLoop = (p && p->variant() == SPF_ANALYSIS_DIR);
|
|
#else
|
|
SgStatement* p = (*stmt)->lexPrev();
|
|
bool isParLoop = (p && p->variant() == DVM_PARALLEL_ON_DIR);
|
|
#endif
|
|
SgExpression* pl = NULL;
|
|
SgExpression* pPl = NULL;
|
|
bool pl_flag = true;
|
|
if (isParLoop){
|
|
#if __SPF
|
|
SgExpression* el = p->expr(0);
|
|
#else
|
|
SgExpression* el = p->expr(1);
|
|
#endif
|
|
pPl = el;
|
|
while (el != NULL) {
|
|
SgExpression* e = el->lhs();
|
|
if (e->variant() == ACC_PRIVATE_OP) {
|
|
pl = e;
|
|
break;
|
|
}
|
|
pPl = el;
|
|
pl_flag = false;
|
|
el = el->rhs();
|
|
}
|
|
//pl->unparsestdout();
|
|
}
|
|
bool isEndDo = fst->isEnddoLoop();
|
|
SgExpression* lh = new SgVarRefExp(fst->symbol());
|
|
SgStatement* fa = new SgAssignStmt(*lh, *fst->start());
|
|
bool needs_goto = true;
|
|
#if !__SPF
|
|
// create goto edge if can not calculate count of loop's iterations
|
|
if (fst->start()->variant() == INT_VAL && fst->end()->variant() == INT_VAL && fst->start()->valueInteger() < fst->end()->valueInteger())
|
|
needs_goto = false;
|
|
#endif
|
|
//fa->setLabel(*(*stmt)->label());
|
|
ControlFlowItem* last;
|
|
ControlFlowItem* emptyAfterDo = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* emptyBeforeDo = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* gotoEndInitial = NULL;
|
|
if (needs_goto) {
|
|
SgExpression* sendc = new SgExpression(GT_OP, new SgVarRefExp(fst->symbol()), fst->end(), NULL);
|
|
gotoEndInitial = new ControlFlowItem(sendc, emptyAfterDo, emptyBeforeDo, NULL, currentProcedure, true);
|
|
gotoEndInitial->setOriginalStatement(fst);
|
|
}
|
|
ControlFlowItem* stcf = new ControlFlowItem(fa, needs_goto ? gotoEndInitial : emptyBeforeDo, currentProcedure);
|
|
stcf->setOriginalStatement(fst);
|
|
stcf->setLabel((*stmt)->label());
|
|
SgExpression* rh = new SgExpression(ADD_OP, new SgVarRefExp(fst->symbol()), new SgValueExp(1), NULL);
|
|
SgStatement* add = new SgAssignStmt(*lh, *rh);
|
|
SgExpression* endc = new SgExpression(GT_OP, new SgVarRefExp(fst->symbol()), fst->end(), NULL);
|
|
ControlFlowItem* gotoStart = new ControlFlowItem(NULL, emptyBeforeDo, emptyAfterDo, NULL, currentProcedure);
|
|
ControlFlowItem* gotoEnd = new ControlFlowItem(endc, emptyAfterDo, gotoStart, NULL, currentProcedure);
|
|
gotoEnd->setOriginalStatement(fst);
|
|
if (needs_goto) {
|
|
gotoEnd->SetConditionFriend(gotoEndInitial);
|
|
}
|
|
ControlFlowItem* loop_d = new ControlFlowItem(add, gotoEnd, currentProcedure);
|
|
loop_d->setOriginalStatement(fst);
|
|
ControlFlowItem* loop_emp = new ControlFlowItem(NULL, loop_d, currentProcedure);
|
|
SgVarRefExp* doName = (isSgVarRefExp((*stmt)->expr(2)));
|
|
int lbl = -1;
|
|
if (!isEndDo){
|
|
SgStatement* end = lastStmtOfDoACC(fst);
|
|
if (end->variant() == LOGIF_NODE)
|
|
lbl = end->controlParent()->label()->id();
|
|
else
|
|
lbl = end->label()->id();
|
|
}
|
|
loops->addLoop(lbl, doName ? doName->symbol() : NULL, loop_emp, emptyAfterDo);
|
|
doLoopList->AddLoop(current_file_id, *stmt, fst->start(), fst->end(), fst->step(), fst->symbol());
|
|
if (isParLoop) {
|
|
#if __SPF
|
|
// all loop has depth == 1 ? is it correct?
|
|
int k = 1;
|
|
#else
|
|
SgExpression* par_des = p->expr(2);
|
|
int k = 0;
|
|
while (par_des != NULL && par_des->lhs() != NULL) {
|
|
k++;
|
|
par_des = par_des->rhs();
|
|
}
|
|
#endif
|
|
loops->setParallelDepth(k, pl, p, pPl, pl_flag);
|
|
}
|
|
|
|
if (loops->isLastParallel()) {
|
|
SgExpression* ex = loops->getPrivateList();
|
|
emptyBeforeDo->MakeParloopStart();
|
|
bool f;
|
|
SgExpression* e = loops->getExpressionToModifyPrivateList(&f);
|
|
emptyBeforeDo->setPrivateList(ex, loops->GetParallelStatement(), e, f);
|
|
loop_d->MakeParloopEnd();
|
|
}
|
|
if (isEndDo){
|
|
ControlFlowItem* body;
|
|
if ((body = getControlFlowList(fst->body(), NULL, &last, stmt, loops, calls, commons)) == NULL)
|
|
return NULL;
|
|
emptyBeforeDo->AddNextItem(body);
|
|
loops->endLoop(last);
|
|
}
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(stcf);
|
|
else
|
|
*list = stcf;
|
|
if (isEndDo)
|
|
return (*pred = emptyAfterDo);
|
|
return (*pred = emptyBeforeDo);
|
|
}
|
|
case GOTO_NODE:
|
|
{
|
|
SgGotoStmt* gst = isSgGotoStmt(*stmt);
|
|
ControlFlowItem* gt = new ControlFlowItem(NULL, gst->branchLabel(), NULL, gst->label(), currentProcedure);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(gt);
|
|
else
|
|
*list = gt;
|
|
return (*pred = gt);
|
|
}
|
|
case ARITHIF_NODE:
|
|
{
|
|
SgArithIfStmt* arif = (SgArithIfStmt*)(*stmt);
|
|
ControlFlowItem* gt3 = new ControlFlowItem(NULL, ((SgLabelRefExp*)(*stmt)->expr(1)->rhs()->rhs()->lhs())->label(), NULL, NULL, currentProcedure);
|
|
ControlFlowItem* gt2 = new ControlFlowItem(&SgEqOp(*(arif->conditional()), *new SgValueExp(0)), ((SgLabelRefExp*)(*stmt)->expr(1)->rhs()->lhs())->label(), gt3, NULL, currentProcedure);
|
|
gt2->setOriginalStatement(arif);
|
|
ControlFlowItem* gt1 = new ControlFlowItem(&(*arif->conditional() < *new SgValueExp(0)), ((SgLabelRefExp*)(*stmt)->expr(1)->lhs())->label(), gt2, (*stmt)->label(), currentProcedure);
|
|
gt1->setOriginalStatement(arif);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(gt1);
|
|
else
|
|
*list = gt1;
|
|
return (*pred = gt3);
|
|
}
|
|
case COMGOTO_NODE:
|
|
{
|
|
SgComputedGotoStmt* cgt = (SgComputedGotoStmt*)(*stmt);
|
|
SgExpression* label = cgt->labelList();
|
|
int i = 0;
|
|
SgLabel* lbl = ((SgLabelRefExp *)(label->lhs()))->label();
|
|
ControlFlowItem* gt = new ControlFlowItem(&SgEqOp(*(cgt->exp()), *new SgValueExp(++i)), lbl, NULL, cgt->label(), currentProcedure);
|
|
gt->setOriginalStatement(cgt);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(gt);
|
|
else
|
|
*list = gt;
|
|
ControlFlowItem* old = gt;
|
|
while ((label = label->rhs()))
|
|
{
|
|
lbl = ((SgLabelRefExp *)(label->lhs()))->label();
|
|
gt = new ControlFlowItem(&SgEqOp(*(cgt->exp()), *new SgValueExp(++i)), lbl, NULL, NULL, currentProcedure);
|
|
gt->setOriginalStatement(cgt);
|
|
old->AddNextItem(gt);
|
|
old = gt;
|
|
}
|
|
return (*pred = gt);
|
|
}
|
|
case SWITCH_NODE:
|
|
{
|
|
ControlFlowItem* emptyAfterSwitch = new ControlFlowItem(currentProcedure);
|
|
ControlFlowItem* cur = switchItem(*stmt, emptyAfterSwitch, stmt, loops, calls, commons);
|
|
emptyAfterSwitch->setLabel((*stmt)->label());
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = emptyAfterSwitch);
|
|
}
|
|
case CONT_STAT:
|
|
{
|
|
ControlFlowItem* cur = new ControlFlowItem(NULL, (ControlFlowItem*)NULL, NULL, (*stmt)->label(), currentProcedure);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = loops->checkStatementForLoopEnding(cur->getLabel() ? cur->getLabel()->id() : -1, cur));
|
|
}
|
|
case CYCLE_STMT:
|
|
{
|
|
SgSymbol* ref = (*stmt)->symbol();
|
|
ControlFlowItem* cur = new ControlFlowItem(NULL, loops->getSourceForCycle(ref), NULL, (*stmt)->label(), currentProcedure);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = cur);
|
|
}
|
|
case EXIT_STMT:
|
|
{
|
|
SgSymbol* ref = (*stmt)->symbol();
|
|
ControlFlowItem* cur = new ControlFlowItem(NULL, loops->getSourceForExit(ref), NULL, (*stmt)->label(), currentProcedure);
|
|
if (*pred != NULL)
|
|
(*pred)->AddNextItem(cur);
|
|
else
|
|
*list = cur;
|
|
return (*pred = cur);
|
|
}
|
|
case COMMENT_STAT:
|
|
return *pred;
|
|
case COMM_STAT:
|
|
{
|
|
commons->RegisterCommonBlock(*stmt, currentProcedure);
|
|
return *pred;
|
|
}
|
|
default:
|
|
return *pred;
|
|
//return NULL;
|
|
}
|
|
}
|
|
|
|
ControlFlowGraph::ControlFlowGraph(bool t, bool m, ControlFlowItem* list, ControlFlowItem* end) : temp(t), main(m), refs(1), def(NULL), use(NULL), pri(NULL), common_def(NULL), common_use(NULL), hasBeenAnalyzed(false)
|
|
#ifdef __SPF
|
|
, pointers(set<SymbolKey>())
|
|
#endif
|
|
{
|
|
#if __SPF
|
|
addToCollection(__LINE__, __FILE__, this, 30);
|
|
#endif
|
|
int n = 0;
|
|
ControlFlowItem* orig = list;
|
|
CBasicBlock* prev = NULL;
|
|
CBasicBlock* start = NULL;
|
|
int stmtNo = 0;
|
|
bool ns = list->isEnumerated();
|
|
if (list != NULL && !ns){
|
|
while (list != NULL && list != end)
|
|
{
|
|
list->setStmtNo(++stmtNo);
|
|
list = list->getNext();
|
|
}
|
|
}
|
|
ControlFlowItem* last_prev = NULL;
|
|
list = orig;
|
|
while (list != NULL && list != end)
|
|
{
|
|
CBasicBlock* bb = new CBasicBlock(t, list, ++n, this, list->getProc());
|
|
last = bb;
|
|
bb->setPrev(prev);
|
|
if (prev != NULL){
|
|
prev->setNext(bb);
|
|
if (!last_prev->isUnconditionalJump()){
|
|
bb->addToPrev(prev, last_prev->IsForJumpFlagSet(), false, last_prev);
|
|
prev->addToSucc(bb, last_prev->IsForJumpFlagSet(), false, last_prev);
|
|
}
|
|
}
|
|
if (start == NULL)
|
|
start = bb;
|
|
prev = bb;
|
|
while (list->getNext() != NULL && list->getNext() != end && !list->getNext()->isLeader()){
|
|
list->setBBno(n);
|
|
list = list->getNext();
|
|
}
|
|
list->setBBno(n);
|
|
last_prev = list;
|
|
list = list->getNext();
|
|
}
|
|
list = orig;
|
|
while (list != NULL && list != end)
|
|
{
|
|
ControlFlowItem* target;
|
|
if ((target = list->getJump()) != NULL)
|
|
{
|
|
// //no back edges
|
|
// if (target->getBBno() > list->getBBno())
|
|
// {
|
|
CBasicBlock* tmp1 = start;
|
|
CBasicBlock* tmp2 = start;
|
|
for (int i = 1; i < target->getBBno() || i < list->getBBno(); i++)
|
|
{
|
|
if (i < list->getBBno()) {
|
|
tmp2 = tmp2->getLexNext();
|
|
if (!tmp2)
|
|
break;
|
|
}
|
|
if (i < target->getBBno()) {
|
|
tmp1 = tmp1->getLexNext();
|
|
if (!tmp1)
|
|
break;
|
|
}
|
|
}
|
|
if (tmp1 && tmp2) {
|
|
tmp1->addToPrev(tmp2, list->IsForJumpFlagSet(), true, list);
|
|
tmp2->addToSucc(tmp1, list->IsForJumpFlagSet(), true, list);
|
|
}
|
|
// }
|
|
}
|
|
list = list->getNext();
|
|
}
|
|
start->markAsReached();
|
|
first = start;
|
|
common_use = NULL;
|
|
cuf = false;
|
|
common_def = NULL;
|
|
cdf = false;
|
|
}
|
|
|
|
CommonDataItem* CommonData::IsThisCommonVar(VarItem* item, AnalysedCallsList* call)
|
|
{
|
|
for (CommonDataItem* it = list; it != NULL; it = it->next) {
|
|
if (it->proc == call) {
|
|
for (CommonVarInfo* inf = it->info; inf != NULL; inf = inf->next) {
|
|
if (inf->var && item->var && *inf->var == *item->var)
|
|
return it;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CommonDataItem* CommonData::GetItemForName(const string &name, AnalysedCallsList *call)
|
|
{
|
|
for (CommonDataItem* it = list; it != NULL; it = it->next) {
|
|
if (it->name == name && it->proc == call)
|
|
return it;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CommonData::RegisterCommonBlock(SgStatement *st, AnalysedCallsList *cur)
|
|
{
|
|
//TODO: multiple common blocks in one procedure with same name
|
|
for (SgExpression *common = st->expr(0); common; common = common->rhs())
|
|
{
|
|
bool newBlock = false;
|
|
SgExprListExp* vars = (SgExprListExp*)common->lhs();
|
|
if (vars == NULL)
|
|
continue;
|
|
|
|
const string currCommonName = (common->symbol()) ? common->symbol()->identifier() : "spf_unnamed";
|
|
|
|
CommonDataItem* it = GetItemForName(currCommonName, cur);
|
|
if (!it) {
|
|
it = new CommonDataItem();
|
|
it->cb = st;
|
|
it->name = currCommonName;
|
|
it->isUsable = true;
|
|
it->proc = cur;
|
|
it->first = cur;
|
|
it->onlyScalars = true;
|
|
newBlock = true;
|
|
|
|
for (CommonDataItem *i = list; i != NULL; i = i->next)
|
|
if (i->name == currCommonName && i->isUsable)
|
|
it->first = i->first;
|
|
}
|
|
it->commonRefs.push_back(common);
|
|
|
|
for (int i = 0; i < vars->length(); ++i)
|
|
{
|
|
SgVarRefExp *e = isSgVarRefExp(vars->elem(i));
|
|
if (e && !IS_ARRAY(e->symbol()))
|
|
{
|
|
CommonVarInfo* c = new CommonVarInfo();
|
|
c->var = new CScalarVarEntryInfo(e->symbol());
|
|
c->isPendingLastPrivate = false;
|
|
c->isInUse = false;
|
|
c->parent = it;
|
|
c->next = it->info;
|
|
it->info = c;
|
|
}
|
|
else if (isSgArrayRefExp(vars->elem(i))) {
|
|
it->onlyScalars = false;
|
|
}
|
|
else {
|
|
CommonVarInfo* c = new CommonVarInfo();
|
|
c->var = new CArrayVarEntryInfo(vars->elem(i)->symbol(), isSgArrayRefExp(vars->elem(i)));
|
|
c->isPendingLastPrivate = false;
|
|
c->isInUse = false;
|
|
c->parent = it;
|
|
c->next = it->info;
|
|
it->info = c;
|
|
it->onlyScalars = false;
|
|
}
|
|
}
|
|
|
|
if (newBlock)
|
|
{
|
|
it->next = list;
|
|
list = it;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CommonData::MarkEndOfCommon(AnalysedCallsList* cur)
|
|
{
|
|
for (CommonDataItem* i = list; i != NULL; i = i->next)
|
|
{
|
|
if (i->first == cur)
|
|
i->isUsable = false;
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::markAsReached()
|
|
{
|
|
prev_status = 1;
|
|
BasicBlockItem* s = succ;
|
|
while (s != NULL){
|
|
CBasicBlock* b = s->block;
|
|
if (b->prev_status == -1)
|
|
b->markAsReached();
|
|
s = s->next;
|
|
}
|
|
}
|
|
|
|
bool ControlFlowGraph::ProcessOneParallelLoop(ControlFlowItem* lstart, CBasicBlock* of, CBasicBlock*& p, bool first)
|
|
{
|
|
int stored_fid = SwitchFile(lstart->getProc()->file_id);
|
|
ControlFlowItem* lend;
|
|
if (is_correct != NULL)
|
|
{
|
|
const char* expanded_log;
|
|
char* tmp = NULL;
|
|
if (failed_proc_name)
|
|
{
|
|
tmp = new char[strlen(is_correct) + 2 + strlen(failed_proc_name) + 1];
|
|
strcpy(tmp, is_correct);
|
|
strcat(tmp, ": ");
|
|
strcat(tmp, failed_proc_name);
|
|
expanded_log = tmp;
|
|
}
|
|
else
|
|
expanded_log = is_correct;
|
|
#if __SPF
|
|
const wchar_t* rus = R159;
|
|
Warning("Private analysis is not conducted for loop: '%s'", rus, expanded_log ? expanded_log : "", PRIVATE_ANALYSIS_NOT_CONDUCTED, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("Private analysis is not conducted for loop: '%s'", expanded_log ? expanded_log : "", PRIVATE_ANALYSIS_NOT_CONDUCTED, lstart->getPrivateListStatement());
|
|
#endif
|
|
if (tmp)
|
|
delete[] tmp;
|
|
|
|
}
|
|
else
|
|
{
|
|
while ((lend = p->containsParloopEnd()) == NULL)
|
|
{
|
|
p->PrivateAnalysisForAllCalls();
|
|
p = p->getLexNext();
|
|
ControlFlowItem* mstart;
|
|
if ((mstart = p->containsParloopStart()) != NULL)
|
|
{
|
|
CBasicBlock* mp = p;
|
|
if (first) {
|
|
if (!ProcessOneParallelLoop(mstart, of, mp, false)) {
|
|
SwitchFile(stored_fid);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CBasicBlock* afterParLoop = p->getLexNext()->getLexNext();
|
|
VarSet* l_pri = ControlFlowGraph(true, false, lstart, lend).getPrivate();
|
|
if (is_correct != NULL)
|
|
{
|
|
const char* expanded_log;
|
|
char* tmp = NULL;
|
|
if (failed_proc_name)
|
|
{
|
|
tmp = new char[strlen(is_correct) + 2 + strlen(failed_proc_name) + 1];
|
|
strcpy(tmp, is_correct);
|
|
strcat(tmp, ": ");
|
|
strcat(tmp, failed_proc_name);
|
|
expanded_log = tmp;
|
|
}
|
|
else
|
|
expanded_log = is_correct;
|
|
|
|
#if __SPF
|
|
const wchar_t* rus = R159;
|
|
Warning("Private analysis is not conducted for loop: '%s'", rus, expanded_log ? expanded_log : "", PRIVATE_ANALYSIS_NOT_CONDUCTED, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("Private analysis is not conducted for loop: '%s'", expanded_log ? expanded_log : "", PRIVATE_ANALYSIS_NOT_CONDUCTED, lstart->getPrivateListStatement());
|
|
#endif
|
|
if (tmp)
|
|
delete[] tmp;
|
|
SwitchFile(stored_fid);
|
|
return false;
|
|
}
|
|
VarSet* p_pri = new VarSet();
|
|
SgExpression* ex_p = lstart->getPrivateList();
|
|
if (ex_p != NULL)
|
|
ex_p = ex_p->lhs();
|
|
for (; ex_p != NULL; ex_p = ex_p->rhs())
|
|
{
|
|
SgVarRefExp* pr;
|
|
if (pr = isSgVarRefExp(ex_p->lhs()))
|
|
{
|
|
CScalarVarEntryInfo* tmp = new CScalarVarEntryInfo(pr->symbol());
|
|
p_pri->addToSet(tmp, NULL);
|
|
delete tmp;
|
|
}
|
|
SgArrayRefExp* ar;
|
|
if (ar = isSgArrayRefExp(ex_p->lhs()))
|
|
{
|
|
CArrayVarEntryInfo* tmp = new CArrayVarEntryInfo(ar->symbol(), ar);
|
|
p_pri->addToSet(tmp, NULL);
|
|
delete tmp;
|
|
}
|
|
}
|
|
|
|
VarSet* live = afterParLoop->getLiveIn();
|
|
VarSet* adef = afterParLoop->getDef();
|
|
VarSet* pri = new VarSet();
|
|
VarSet* tmp = new VarSet();
|
|
VarSet* delay = new VarSet();
|
|
tmp->unite(l_pri, false);
|
|
|
|
for (VarItem* exp = tmp->getFirst(); exp != NULL; exp = tmp->getFirst())
|
|
{
|
|
if (!afterParLoop->IsVarDefinedAfterThisBlock(exp->var, false))
|
|
delay->addToSet(exp->var, NULL);
|
|
tmp->remove(exp->var);
|
|
}
|
|
delete tmp;
|
|
pri->unite(l_pri, false);
|
|
pri->minus(live, true);
|
|
privateDelayedList = new PrivateDelayedItem(pri, p_pri, l_pri, lstart, privateDelayedList, this, delay, current_file_id);
|
|
of->SetDelayedData(privateDelayedList);
|
|
}
|
|
SwitchFile(stored_fid);
|
|
return true;
|
|
}
|
|
|
|
void ControlFlowGraph::privateAnalyzer()
|
|
{
|
|
if (hasBeenAnalyzed)
|
|
return;
|
|
CBasicBlock* p = first;
|
|
/*
|
|
printf("GRAPH:\n");
|
|
while (p != NULL){
|
|
printf("block %d: ", p->getNum());
|
|
if (p->containsParloopStart())
|
|
printf("start");
|
|
if (p->containsParloopEnd())
|
|
printf("end");
|
|
p->print();
|
|
p = p->getLexNext();
|
|
}
|
|
*/
|
|
p = first;
|
|
liveAnalysis();
|
|
while (1)
|
|
{
|
|
ControlFlowItem* lstart;
|
|
CBasicBlock* of = p;
|
|
p->PrivateAnalysisForAllCalls();
|
|
if ((lstart = p->containsParloopStart()) != NULL)
|
|
{
|
|
if (!ProcessOneParallelLoop(lstart, of, p, true))
|
|
break;
|
|
}
|
|
if (p == last)
|
|
break;
|
|
p = p->getLexNext();
|
|
}
|
|
hasBeenAnalyzed = true;
|
|
}
|
|
|
|
/*#ifdef __SPF
|
|
void PrivateDelayedItem::PrintWarnings()
|
|
{
|
|
if (next)
|
|
next->PrintWarnings();
|
|
lp->minus(detected);
|
|
while (!detected->isEmpty()) {
|
|
SgVarRefExp* var = detected->getFirst();
|
|
detected->remove(var);
|
|
Warning("Variable '%s' detected as private", var->unparse(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
}
|
|
while (!lp->isEmpty()) {
|
|
SgVarRefExp* var = lp->getFirst();
|
|
lp->remove(var);
|
|
Warning("Variable '%s' detected as last private", var->unparse(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
}
|
|
if (detected)
|
|
delete detected;
|
|
if (original)
|
|
delete original;
|
|
if (lp)
|
|
delete lp;
|
|
}
|
|
#else*/
|
|
|
|
bool CArrayVarEntryInfo::HasActiveElements() const
|
|
{
|
|
bool result = false;
|
|
if (disabled)
|
|
return false;
|
|
if (subscripts == 0)
|
|
return true;
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
if (!data[i].defined)
|
|
return false;
|
|
if (data[i].left_bound != data[i].right_bound)
|
|
result = true;
|
|
if (data[i].left_bound == data[i].right_bound && data[i].bound_modifiers[0] <= data[i].bound_modifiers[1])
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void CArrayVarEntryInfo::MakeInactive()
|
|
{
|
|
disabled = true;
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
data[i].left_bound = data[i].right_bound = NULL;
|
|
data[i].bound_modifiers[0] = data[i].bound_modifiers[1] = 0;
|
|
}
|
|
}
|
|
|
|
void PrivateDelayedItem::PrintWarnings()
|
|
{
|
|
if (next)
|
|
next->PrintWarnings();
|
|
int stored_fid = SwitchFile(file_id);
|
|
total_privates += detected->count();
|
|
total_pl++;
|
|
lp->minus(detected);
|
|
detected->LeaveOnlyRecords();
|
|
detected->RemoveDoubtfulCommonVars(lstart->getProc());
|
|
VarSet* test1 = new VarSet();
|
|
test1->unite(detected, false);
|
|
VarSet* test2 = new VarSet();
|
|
test2->unite(original, false);
|
|
test2->minus(detected);
|
|
test1->minus(original);
|
|
int extra = 0, missing = 0;
|
|
SgExpression* prl = lstart->getPrivateList();
|
|
SgStatement* prs = lstart->getPrivateListStatement();
|
|
if (prl == NULL && !test1->isEmpty())
|
|
{
|
|
SgExpression* lst = new SgExprListExp();
|
|
prl = new SgExpression(ACC_PRIVATE_OP);
|
|
lst->setLhs(prl);
|
|
lst->setRhs(NULL);
|
|
#if __SPF
|
|
SgExpression* clauses = prs->expr(0);
|
|
#else
|
|
SgExpression* clauses = prs->expr(1);
|
|
#endif
|
|
if (clauses) {
|
|
while (clauses->rhs() != NULL)
|
|
clauses = clauses->rhs();
|
|
clauses->setRhs(lst);
|
|
}
|
|
else {
|
|
#if __SPF
|
|
prs->setExpression(0, *lst);
|
|
#else
|
|
prs->setExpression(1, *lst);
|
|
#endif
|
|
}
|
|
}
|
|
SgExpression* op = prl;
|
|
|
|
while (!test2->isEmpty()) {
|
|
//printf("EXTRA IN PRIVATE LIST: ");
|
|
//test2->print();
|
|
extra = 1;
|
|
VarItem* var = test2->getFirst();
|
|
CVarEntryInfo* syb = var->var->Clone();
|
|
int change_fid = var->file_id;
|
|
test2->remove(var->var);
|
|
int stored_fid = SwitchFile(change_fid);
|
|
if (syb->GetVarType() != VAR_REF_ARRAY_EXP)
|
|
{
|
|
#if __SPF
|
|
const wchar_t* rus = R160;
|
|
Warning("var '%s' from private list wasn't classified as private", rus, syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_REMOVE_VAR, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("var '%s' from private list wasn't classified as private", syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_REMOVE_VAR, lstart->getPrivateListStatement());
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
CArrayVarEntryInfo* tt = (CArrayVarEntryInfo*)syb;
|
|
if (tt->HasActiveElements())
|
|
{
|
|
#if __SPF
|
|
const wchar_t* rus = R161;
|
|
Warning("array '%s' from private list wasn't classified as private", rus, syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_REMOVE_VAR, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("array '%s' from private list wasn't classified as private", syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_REMOVE_VAR, lstart->getPrivateListStatement());
|
|
#endif
|
|
}
|
|
}
|
|
delete(syb);
|
|
SwitchFile(stored_fid);
|
|
}
|
|
while (!test1->isEmpty()) {
|
|
//printf("MISSING IN PRIVATE LIST: ");
|
|
//test1->print();
|
|
missing = 1;
|
|
VarItem* var = test1->getFirst();
|
|
CVarEntryInfo* syb = var->var->Clone();
|
|
int change_fid = var->file_id;
|
|
test1->remove(var->var);
|
|
int stored_fid = SwitchFile(change_fid);
|
|
if (syb->GetVarType() != VAR_REF_ARRAY_EXP) {
|
|
#if __SPF
|
|
const wchar_t* rus = R162;
|
|
Note("add private scalar '%s'", rus, syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("var '%s' was added to private list", syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
#endif
|
|
SgExprListExp* nls = new SgExprListExp();
|
|
SgVarRefExp* nvr = new SgVarRefExp(syb->GetSymbol());
|
|
nls->setLhs(nvr);
|
|
nls->setRhs(prl->lhs());
|
|
prl->setLhs(nls);
|
|
}
|
|
else
|
|
{
|
|
CArrayVarEntryInfo* tt = (CArrayVarEntryInfo*)syb;
|
|
if (tt->HasActiveElements())
|
|
{
|
|
#if __SPF
|
|
const wchar_t* rus = R163;
|
|
Note("add private array '%s'", rus, syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
#else
|
|
Warning("var '%s' was added to private list", syb->GetSymbol()->identifier(), PRIVATE_ANALYSIS_ADD_VAR, lstart->getPrivateListStatement());
|
|
#endif
|
|
|
|
// TODO: need to check all situation before commit it to release
|
|
#if !__SPF
|
|
SgExprListExp *nls = new SgExprListExp();
|
|
SgArrayRefExp *nvr = new SgArrayRefExp(*syb->GetSymbol());
|
|
nls->setLhs(nvr);
|
|
nls->setRhs(prl->lhs());
|
|
prl->setLhs(nls);
|
|
#endif
|
|
}
|
|
}
|
|
delete(syb);
|
|
SwitchFile(stored_fid);
|
|
|
|
/*printf("modified parallel stmt:\n");
|
|
prs->unparsestdout();
|
|
printf("\n");*/
|
|
}
|
|
if (extra == 0 && missing == 0) {
|
|
#if ACCAN_DEBUG
|
|
Warning("Correct", "", 0, lstart->getPrivateListStatement());
|
|
#endif
|
|
}
|
|
//printf("PRIVATE VARS: ");
|
|
//detected->print();
|
|
//printf("DECLARATION: ");
|
|
//p_pri->print();
|
|
//printf("LAST PRIVATE VARS: ");
|
|
//lp->print();
|
|
if (test1)
|
|
delete test1;
|
|
|
|
|
|
if (test2)
|
|
delete test2;
|
|
|
|
if (detected)
|
|
delete detected;
|
|
|
|
if (original)
|
|
delete original;
|
|
|
|
if (lp)
|
|
delete lp;
|
|
|
|
SwitchFile(stored_fid);
|
|
}
|
|
//#endif
|
|
|
|
ControlFlowItem* doLoops::checkStatementForLoopEnding(int label, ControlFlowItem* last)
|
|
{
|
|
|
|
if (current == NULL || label == -1 || label != current->getLabel())
|
|
return last;
|
|
return checkStatementForLoopEnding(label, endLoop(last));
|
|
}
|
|
|
|
doLoopItem* doLoops::findLoop(SgSymbol* s)
|
|
{
|
|
doLoopItem* l = first;
|
|
while (l != NULL){
|
|
if (l->getName() == s)
|
|
return l;
|
|
l = l->getNext();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void doLoops::addLoop(int l, SgSymbol* s, ControlFlowItem* i, ControlFlowItem* e)
|
|
{
|
|
doLoopItem* nl = new doLoopItem(l, s, i, e);
|
|
if (first == NULL)
|
|
first = current = nl;
|
|
else{
|
|
current->setNext(nl);
|
|
nl->HandleNewItem(current);
|
|
current = nl;
|
|
}
|
|
}
|
|
|
|
ControlFlowItem* doLoops::endLoop(ControlFlowItem* last)
|
|
{
|
|
doLoopItem* removed = current;
|
|
if (first == current)
|
|
first = current = NULL;
|
|
else{
|
|
doLoopItem* prev = first;
|
|
while (prev->getNext() != current)
|
|
prev = prev->getNext();
|
|
prev->setNext(NULL);
|
|
current = prev;
|
|
}
|
|
last->AddNextItem(removed->getSourceForCycle());
|
|
ControlFlowItem* empty = removed->getSourceForExit();
|
|
delete removed;
|
|
return empty;
|
|
}
|
|
|
|
VarSet* ControlFlowGraph::getPrivate()
|
|
{
|
|
//printControlFlowList(first->getStart(), last->getStart());
|
|
if (pri == NULL)
|
|
{
|
|
bool same = false;
|
|
int it = 0;
|
|
CBasicBlock* p = first;
|
|
/*
|
|
printf("GRAPH:\n");
|
|
while (p != NULL){
|
|
printf("block %d: ", p->getNum());
|
|
p->print();
|
|
p = p->getLexNext();
|
|
}
|
|
*/
|
|
p = first;
|
|
while (!same){
|
|
p = first;
|
|
same = true;
|
|
while (p != NULL){
|
|
same = p->stepMrdIn(false) && same;
|
|
same = p->stepMrdOut(false) && same;
|
|
p = p->getLexNext();
|
|
}
|
|
it++;
|
|
//printf("iters: %d\n", it);
|
|
}
|
|
p = first;
|
|
while (p != NULL) {
|
|
p->stepMrdIn(true);
|
|
p->stepMrdOut(true);
|
|
//p->getMrdIn(false)->print();
|
|
p = p->getLexNext();
|
|
}
|
|
|
|
p = first;
|
|
VarSet* res = new VarSet();
|
|
VarSet* loc = new VarSet();
|
|
bool il = false;
|
|
while (p != NULL)
|
|
{
|
|
res->unite(p->getUse(), false);
|
|
loc->unite(p->getDef(), false);
|
|
p = p->getLexNext();
|
|
}
|
|
//printf("USE: ");
|
|
//res->print();
|
|
//printf("LOC: ");
|
|
//loc->print();
|
|
res->unite(loc, false);
|
|
//printf("GETUSE: ");
|
|
//getUse()->print();
|
|
|
|
//res->minus(getUse()); //test!
|
|
res->minusFinalize(getUse(), true);
|
|
pri = res;
|
|
}
|
|
return pri;
|
|
}
|
|
|
|
void ControlFlowGraph::liveAnalysis()
|
|
{
|
|
bool same = false;
|
|
int it = 0;
|
|
CBasicBlock* p = first;
|
|
p = first;
|
|
while (!same){
|
|
p = last;
|
|
same = true;
|
|
while (p != NULL){
|
|
same = p->stepLVOut() && same;
|
|
same = p->stepLVIn() && same;
|
|
p = p->getLexPrev();
|
|
}
|
|
it++;
|
|
//printf("iters: %d\n", it);
|
|
}
|
|
}
|
|
|
|
VarSet* ControlFlowGraph::getUse()
|
|
{
|
|
if (use == NULL)
|
|
{
|
|
CBasicBlock* p = first;
|
|
VarSet* res = new VarSet();
|
|
while (p != NULL)
|
|
{
|
|
VarSet* tmp = new VarSet();
|
|
tmp->unite(p->getUse(), false);
|
|
tmp->minus(p->getMrdIn(false));
|
|
//printf("BLOCK %d INSTR %d USE: ", p->getNum(), p->getStart()->getStmtNo());
|
|
//tmp->print();
|
|
res->unite(tmp, false);
|
|
delete tmp;
|
|
p = p->getLexNext();
|
|
}
|
|
use = res;
|
|
|
|
}
|
|
if (!cuf)
|
|
{
|
|
AnalysedCallsList* call = first->getStart()->getProc();
|
|
cuf = true;
|
|
if (call) {
|
|
CommonVarSet* s = pCommons->GetCommonsForVarSet(use, call);
|
|
common_use = s;
|
|
for (CBasicBlock* i = first; i != NULL; i = i->getLexNext()){
|
|
for (CommonVarSet* c = i->getCommonUse(); c != NULL; c = c->next) {
|
|
/*
|
|
CommonVarSet* n = new CommonVarSet();
|
|
n->cvd = c->cvd;
|
|
n->cvd->refs++;
|
|
*/
|
|
CommonVarSet* n = new CommonVarSet(*c);
|
|
CommonVarSet* t;
|
|
for (t = n; t->next != NULL; t = t->next);
|
|
t->next = common_use;
|
|
common_use = n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return use;
|
|
}
|
|
|
|
VarSet* ControlFlowGraph::getDef()
|
|
{
|
|
if (def == NULL) {
|
|
def = new VarSet();
|
|
def->unite(last->getMrdOut(false), true);
|
|
}
|
|
if (!cdf)
|
|
{
|
|
AnalysedCallsList* call = first->getStart()->getProc();
|
|
if (call) {
|
|
cdf = true;
|
|
CommonVarSet* s = pCommons->GetCommonsForVarSet(def, call);
|
|
common_def = s;
|
|
for (CBasicBlock* i = first; i != NULL; i = i->getLexNext()) {
|
|
for (CommonVarSet* c = i->getCommonDef(); c != NULL; c = c->next) {
|
|
/*
|
|
CommonVarSet* n = new CommonVarSet();
|
|
n->cvd = c->cvd;
|
|
n->cvd->refs++;
|
|
*/
|
|
CommonVarSet *n = new CommonVarSet(*c);
|
|
CommonVarSet* t;
|
|
for (t = n; t->next != NULL; t = t->next);
|
|
t->next = common_def;
|
|
common_def = n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return def;
|
|
}
|
|
|
|
CommonVarSet* CommonData::GetCommonsForVarSet(VarSet* set, AnalysedCallsList* call)
|
|
{
|
|
CommonVarSet* res = NULL;
|
|
for (CommonDataItem* i = list; i != NULL; i = i->next) {
|
|
if (i->proc == call) {
|
|
for (CommonVarInfo* v = i->info; v != NULL; v = v->next) {
|
|
if (set->belongs(v->var)) {
|
|
CommonVarSet* n = new CommonVarSet();
|
|
n->cvd = v;
|
|
n->next = res;
|
|
res = n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void CBasicBlock::PrivateAnalysisForAllCalls()
|
|
{
|
|
ControlFlowItem* p = start;
|
|
while (p != NULL && (p == start || !p->isLeader())) {
|
|
AnalysedCallsList* c = p->getCall();
|
|
const char* oic = is_correct;
|
|
const char* fpn = failed_proc_name;
|
|
is_correct = NULL;
|
|
failed_proc_name = NULL;
|
|
if (c != NULL && c != (AnalysedCallsList*)(-1) && c != (AnalysedCallsList*)(-2) && c->header != NULL && !c->hasBeenAnalysed) {
|
|
c->hasBeenAnalysed = true;
|
|
|
|
int stored_fid = SwitchFile(c->file_id);
|
|
|
|
c->graph->privateAnalyzer();
|
|
|
|
SwitchFile(stored_fid);
|
|
|
|
}
|
|
is_correct = oic;
|
|
failed_proc_name = fpn;
|
|
p = p->getNext();
|
|
}
|
|
return;
|
|
}
|
|
|
|
ControlFlowItem* CBasicBlock::containsParloopEnd()
|
|
{
|
|
ControlFlowItem* p = start;
|
|
while (p != NULL && (p == start || !p->isLeader())){
|
|
if (p->IsParloopEnd())
|
|
return p;
|
|
p = p->getNext();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ControlFlowItem* CBasicBlock::containsParloopStart()
|
|
{
|
|
ControlFlowItem* p = start;
|
|
while (p != NULL && (p == start || !p->isLeader())){
|
|
if (p->IsParloopStart())
|
|
return p;
|
|
p = p->getNext();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CBasicBlock::print()
|
|
{
|
|
printf("block %d: prev: ", num);
|
|
BasicBlockItem* p = prev;
|
|
while (p != NULL){
|
|
printf("%d ", p->block->num);
|
|
p = p->next;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
ControlFlowItem* CBasicBlock::getStart()
|
|
{
|
|
return start;
|
|
}
|
|
|
|
ControlFlowItem* CBasicBlock::getEnd()
|
|
{
|
|
ControlFlowItem* p = start;
|
|
ControlFlowItem* end = p;
|
|
while (p != NULL && (p == start || !p->isLeader())){
|
|
end = p;
|
|
p = p->getNext();
|
|
}
|
|
return end;
|
|
}
|
|
|
|
VarSet* CBasicBlock::getLVOut()
|
|
{
|
|
if (lv_out == NULL)
|
|
{
|
|
VarSet* res = new VarSet();
|
|
BasicBlockItem* p = succ;
|
|
bool first = true;
|
|
while (p != NULL)
|
|
{
|
|
CBasicBlock* b = p->block;
|
|
if (b != NULL && !b->lv_undef)
|
|
{
|
|
res->unite(b->getLVIn(), false);
|
|
}
|
|
p = p->next;
|
|
}
|
|
lv_out = res;
|
|
}
|
|
return lv_out;
|
|
}
|
|
|
|
VarSet* CBasicBlock::getLVIn()
|
|
{
|
|
if (lv_in == NULL)
|
|
{
|
|
VarSet* res = new VarSet();
|
|
res->unite(getLVOut(), false);
|
|
res->minus(getDef());
|
|
res->unite(getUse(), false);
|
|
lv_in = res;
|
|
}
|
|
return lv_in;
|
|
}
|
|
|
|
bool CBasicBlock::IsVarDefinedAfterThisBlock(CVarEntryInfo* var, bool os)
|
|
{
|
|
findentity = var;
|
|
if (def->belongs(var, os)) {
|
|
findentity = NULL;
|
|
return true;
|
|
}
|
|
BasicBlockItem* p = succ;
|
|
while (p != NULL)
|
|
{
|
|
CBasicBlock* b = p->block;
|
|
if (b->ShouldThisBlockBeCheckedAgain(var) && b->IsVarDefinedAfterThisBlock(var, os)) {
|
|
findentity = NULL;
|
|
return true;
|
|
}
|
|
p = p->next;
|
|
}
|
|
findentity = NULL;
|
|
return false;
|
|
}
|
|
|
|
bool CBasicBlock::stepLVOut()
|
|
{
|
|
if (old_lv_out)
|
|
delete old_lv_out;
|
|
|
|
old_lv_out = lv_out;
|
|
lv_out = NULL;
|
|
getLVOut();
|
|
lv_undef = false;
|
|
//printf("block %d\n", num);
|
|
//old_mrd_out->print();
|
|
//mrd_out->print();
|
|
return (lv_out->equal(old_lv_out));
|
|
//return true;
|
|
}
|
|
|
|
bool CBasicBlock::stepLVIn()
|
|
{
|
|
if (old_lv_in)
|
|
delete old_lv_in;
|
|
|
|
old_lv_in = lv_in;
|
|
lv_in = NULL;
|
|
getLVIn();
|
|
return (lv_in->equal(old_lv_in));
|
|
//return true;
|
|
}
|
|
|
|
VarSet* CBasicBlock::getMrdIn(bool la)
|
|
{
|
|
if (mrd_in == NULL)
|
|
{
|
|
VarSet* res = new VarSet();
|
|
BasicBlockItem* p = prev;
|
|
bool first = true;
|
|
|
|
while (p != NULL)
|
|
{
|
|
CBasicBlock* b = p->block;
|
|
if (b != NULL && !b->undef && b->hasPrev())
|
|
{
|
|
if (first) {
|
|
res->unite(b->getMrdOut(la), la);
|
|
first = false;
|
|
}
|
|
else
|
|
res->intersect(b->getMrdOut(la), la, true);
|
|
}
|
|
p = p->next;
|
|
}
|
|
mrd_in = res;
|
|
}
|
|
return mrd_in;
|
|
}
|
|
|
|
bool CBasicBlock::hasPrev()
|
|
{
|
|
return prev_status == 1;
|
|
}
|
|
|
|
VarSet* CBasicBlock::getMrdOut(bool la)
|
|
{
|
|
if (mrd_out == NULL)
|
|
{
|
|
VarSet* res = new VarSet();
|
|
res->unite(getMrdIn(la), la);
|
|
res->unite(getDef(), la);
|
|
mrd_out = res;
|
|
//printf("BLOCK %d INSTR %d MRDOUT: ", num, start->getStmtNo());
|
|
//mrd_out->print();
|
|
//print();
|
|
}
|
|
return mrd_out;
|
|
}
|
|
|
|
bool CBasicBlock::stepMrdOut(bool la)
|
|
{
|
|
if (old_mrd_out)
|
|
delete old_mrd_out;
|
|
|
|
old_mrd_out = mrd_out;
|
|
mrd_out = NULL;
|
|
getMrdOut(la);
|
|
undef = false;
|
|
//printf("block %d\n", num);
|
|
//old_mrd_out->print();
|
|
//mrd_out->print();
|
|
return (mrd_out->equal(old_mrd_out));
|
|
//return true;
|
|
}
|
|
|
|
bool CBasicBlock::stepMrdIn(bool la)
|
|
{
|
|
if (old_mrd_in)
|
|
delete old_mrd_in;
|
|
|
|
old_mrd_in = mrd_in;
|
|
mrd_in = NULL;
|
|
getMrdIn(la);
|
|
return (mrd_in->equal(old_mrd_in));
|
|
//return true;
|
|
}
|
|
|
|
bool IsPresentInExprList(SgExpression* ex, CExprList* lst)
|
|
{
|
|
while (lst != NULL) {
|
|
if (lst->entry == ex)
|
|
return true;
|
|
lst = lst->next;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CRecordVarEntryInfo* AddRecordVarRef(SgRecordRefExp* ref)
|
|
{
|
|
if (isSgRecordRefExp(ref->lhs())) {
|
|
CVarEntryInfo* parent = AddRecordVarRef(isSgRecordRefExp(ref->lhs()));
|
|
if (parent)
|
|
return new CRecordVarEntryInfo(ref->rhs()->symbol(), parent);
|
|
return NULL;
|
|
}
|
|
if (isSgVarRefExp(ref->lhs())) {
|
|
CVarEntryInfo* parent = new CScalarVarEntryInfo(isSgVarRefExp(ref->lhs())->symbol());
|
|
return new CRecordVarEntryInfo(ref->rhs()->symbol(), parent);
|
|
}
|
|
if (isSgArrayRefExp(ref->lhs())) {
|
|
CVarEntryInfo* parent = new CArrayVarEntryInfo(isSgArrayRefExp(ref->lhs())->symbol(), isSgArrayRefExp(ref->lhs()));
|
|
return new CRecordVarEntryInfo(ref->rhs()->symbol(), parent);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CBasicBlock::AddOneExpressionToUse(SgExpression* ex, SgStatement* st, CArrayVarEntryInfo* v)
|
|
{
|
|
CVarEntryInfo* var = NULL;
|
|
SgVarRefExp* r;
|
|
if ((r = isSgVarRefExp(ex)))
|
|
var = new CScalarVarEntryInfo(r->symbol());
|
|
SgArrayRefExp* ar;
|
|
if ((ar = isSgArrayRefExp(ex))) {
|
|
if (!v)
|
|
var = new CArrayVarEntryInfo(ar->symbol(), ar);
|
|
else {
|
|
var = v->Clone();
|
|
var->SwitchSymbol(ar->symbol());
|
|
}
|
|
}
|
|
SgRecordRefExp* rr;
|
|
if ((rr = isSgRecordRefExp(ex)))
|
|
var = AddRecordVarRef(rr);
|
|
if (var) {
|
|
var->RegisterUsage(def, use, st);
|
|
delete var;
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::AddOneExpressionToDef(SgExpression* ex, SgStatement* st, CArrayVarEntryInfo* v)
|
|
{
|
|
CVarEntryInfo* var = NULL;
|
|
SgVarRefExp* r;
|
|
if ((r = isSgVarRefExp(ex)))
|
|
var = new CScalarVarEntryInfo(r->symbol());
|
|
SgRecordRefExp* rr;
|
|
if ((rr = isSgRecordRefExp(ex)))
|
|
var = AddRecordVarRef(rr);
|
|
SgArrayRefExp* ar;
|
|
if ((ar = isSgArrayRefExp(ex))) {
|
|
if (!v)
|
|
var = new CArrayVarEntryInfo(ar->symbol(), ar);
|
|
else {
|
|
var = v->Clone();
|
|
var->SwitchSymbol(ar->symbol());
|
|
}
|
|
}
|
|
if (var) {
|
|
var->RegisterDefinition(def, use, st);
|
|
delete var;
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::addExprToUse(SgExpression* ex, CArrayVarEntryInfo* v = NULL, CExprList* lst = NULL)
|
|
{
|
|
if (ex != NULL)
|
|
{
|
|
CExprList* cur = new CExprList();
|
|
cur->entry = ex;
|
|
cur->next = lst;
|
|
SgFunctionCallExp* f = isSgFunctionCallExp(ex);
|
|
if (!f) {
|
|
if (!IsPresentInExprList(ex->lhs(), cur))
|
|
addExprToUse(ex->lhs(), v, cur);
|
|
if (!isSgUnaryExp(ex))
|
|
if (!IsPresentInExprList(ex->rhs(), cur))
|
|
addExprToUse(ex->rhs(), v, cur);
|
|
AddOneExpressionToUse(ex, NULL, v);
|
|
}
|
|
delete cur;
|
|
/*
|
|
SgVarRefExp* r;
|
|
//printf(" %s\n", f->funName()->identifier());
|
|
bool intr = isIntrinsicFunctionNameACC(f->funName()->identifier()) && !IsUserFunctionACC(f->funName());
|
|
bool pure = IsPureProcedureACC(f->funName());
|
|
if (!intr && !pure){
|
|
printf("function not intristic or pure: %s\n", f->funName()->identifier());
|
|
is_correct = false;
|
|
return;
|
|
}
|
|
if (intr) {
|
|
ProcessIntristicProcedure(true, f->numberOfArgs(), f);
|
|
return;
|
|
}
|
|
ProcessProcedureHeader(true, isSgProcHedrStmt(GRAPHNODE(f->funName())->st_header), f);
|
|
*/
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::ProcessIntrinsicProcedure(bool isF, int narg, void* f, const char* name)
|
|
{
|
|
for (int i = 0; i < narg; i++) {
|
|
SgExpression* ar = GetProcedureArgument(isF, f, i);
|
|
if (IsAnIntrinsicSubroutine(name))
|
|
{
|
|
SgExpression* v = CheckIntrinsicParameterFlag(name, i, ar, INTRINSIC_IN);
|
|
if (v)
|
|
addExprToUse(v);
|
|
}
|
|
else
|
|
addExprToUse(ar);
|
|
|
|
AddOneExpressionToDef(CheckIntrinsicParameterFlag(name, i, ar, INTRINSIC_OUT), NULL, NULL);
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::ProcessProcedureWithoutBody(bool isF, void* f, bool out)
|
|
{
|
|
for (int i = 0; i < GetNumberOfArguments(isF, f); i++){
|
|
addExprToUse(GetProcedureArgument(isF, f, i));
|
|
if (out)
|
|
AddOneExpressionToDef(GetProcedureArgument(isF, f, i), NULL, NULL);
|
|
}
|
|
}
|
|
|
|
SgSymbol* CBasicBlock::GetProcedureName(bool isFunc, void* f)
|
|
{
|
|
if (isFunc) {
|
|
SgFunctionCallExp* fc = (SgFunctionCallExp*)f;
|
|
return fc->funName();
|
|
}
|
|
SgCallStmt* pc = (SgCallStmt*)f;
|
|
return pc->name();
|
|
}
|
|
|
|
int GetNumberOfArguments(bool isF, void* f)
|
|
{
|
|
if (isF) {
|
|
SgFunctionCallExp* fc = (SgFunctionCallExp*)f;
|
|
return fc->numberOfArgs();
|
|
}
|
|
SgCallStmt* pc = (SgCallStmt*)f;
|
|
return pc->numberOfArgs();
|
|
}
|
|
|
|
SgExpression* GetProcedureArgument(bool isF, void *f, const int i)
|
|
{
|
|
SgExpression *arg = NULL;
|
|
if (isF)
|
|
{
|
|
SgFunctionCallExp* fc = (SgFunctionCallExp*)f;
|
|
arg = fc->arg(i);
|
|
}
|
|
else
|
|
{
|
|
SgCallStmt *pc = (SgCallStmt*)f;
|
|
arg = pc->arg(i);
|
|
}
|
|
return arg;
|
|
}
|
|
|
|
void CBasicBlock::ProcessProcedureHeader(bool isF, SgProcHedrStmt *header, void *f, const char* name)
|
|
{
|
|
if (!header)
|
|
{
|
|
is_correct = "no header found";
|
|
failed_proc_name = name;
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < header->numberOfParameters(); ++i)
|
|
{
|
|
int stored = SwitchFile(header->getFileId());
|
|
SgSymbol *arg = header->parameter(i);
|
|
SwitchFile(stored);
|
|
|
|
if (arg->attributes() & (IN_BIT))
|
|
{
|
|
SgExpression *ar = GetProcedureArgument(isF, f, i);
|
|
addExprToUse(ar);
|
|
}
|
|
else if (arg->attributes() & (INOUT_BIT))
|
|
{
|
|
addExprToUse(GetProcedureArgument(isF, f, i));
|
|
AddOneExpressionToDef(GetProcedureArgument(isF, f, i), NULL, NULL);
|
|
}
|
|
else if (arg->attributes() & (OUT_BIT))
|
|
AddOneExpressionToDef(GetProcedureArgument(isF, f, i), NULL, NULL);
|
|
else
|
|
{
|
|
is_correct = "no bitflag set for pure procedure";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AnalysedCallsList::isArgIn(int i, CArrayVarEntryInfo** p)
|
|
{
|
|
int stored = SwitchFile(this->file_id);
|
|
SgProcHedrStmt* h = isSgProcHedrStmt(header);
|
|
VarSet* use = graph->getUse();
|
|
SgSymbol* par = h->parameter(i);
|
|
/*
|
|
CScalarVarEntryInfo* var = new CScalarVarEntryInfo(par);
|
|
bool result = false;
|
|
if (use->belongs(var))
|
|
result = true;
|
|
delete var;
|
|
*/
|
|
VarItem* result = use->belongs(par);
|
|
if (result && result->var->GetVarType() == VAR_REF_ARRAY_EXP && p)
|
|
*p = (CArrayVarEntryInfo*)result->var;
|
|
SwitchFile(stored);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AnalysedCallsList::isArgOut(int i, CArrayVarEntryInfo** p)
|
|
{
|
|
int stored = SwitchFile(this->file_id);
|
|
SgProcHedrStmt* h = isSgProcHedrStmt(header);
|
|
graph->privateAnalyzer();
|
|
VarSet* def = graph->getDef();
|
|
SgSymbol* par = h->parameter(i);
|
|
/*
|
|
CScalarVarEntryInfo* var = new CScalarVarEntryInfo(par);
|
|
bool result = false;
|
|
if (def->belongs(var))
|
|
result = true;
|
|
delete var;
|
|
*/
|
|
VarItem* result = def->belongs(par);
|
|
if (result && result->var->GetVarType() == VAR_REF_ARRAY_EXP && p)
|
|
*p = (CArrayVarEntryInfo*)result->var;
|
|
SwitchFile(stored);
|
|
|
|
return result;
|
|
}
|
|
|
|
void CommonData::MarkAsUsed(VarSet* use, AnalysedCallsList* lst)
|
|
{
|
|
for (CommonDataItem* it = list; it != NULL; it = it->next) {
|
|
if (it->proc == lst) {
|
|
for (CommonVarInfo* v = it->info; v != NULL; v = v->next) {
|
|
CVarEntryInfo* r = v->var;
|
|
if (use->belongs(r))
|
|
v->isInUse = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBasicBlock::ProcessUserProcedure(bool isFun, void* call, AnalysedCallsList* c)
|
|
{
|
|
/*
|
|
if (c == NULL || c->graph == NULL) {
|
|
is_correct = "no body found for procedure";
|
|
if (c != NULL)
|
|
failed_proc_name = c->funName;
|
|
else
|
|
failed_proc_name = NULL;
|
|
return;
|
|
}
|
|
*/
|
|
if (c != (AnalysedCallsList*)(-1) && c != (AnalysedCallsList*)(-2) && c != NULL && c->graph != NULL)
|
|
{
|
|
int stored_file_id = SwitchFile(c->file_id);
|
|
c->graph->getPrivate(); //all sets actually
|
|
SgStatement *cp = c->header->controlParent();
|
|
SwitchFile(stored_file_id);
|
|
|
|
if (proc && proc->header->variant() == PROC_HEDR && cp == proc->header) {
|
|
VarSet* use_c = new VarSet();
|
|
use_c->unite(c->graph->getUse(), false);
|
|
for (VarItem* exp = use_c->getFirst(); exp != NULL; exp = use_c->getFirst()) {
|
|
if (exp->var->GetSymbol()->scope() == proc->header) {
|
|
addExprToUse(new SgVarRefExp(exp->var->GetSymbol())); // TESTING
|
|
}
|
|
use_c->remove(exp->var);
|
|
}
|
|
delete use_c;
|
|
VarSet* def_c = new VarSet();
|
|
def_c->unite(c->graph->getDef(), true);
|
|
for (VarItem* exp = def_c->getFirst(); exp != NULL; exp = def_c->getFirst()) {
|
|
if (exp->var->GetSymbol()->scope() == proc->header) {
|
|
def->addToSet(exp->var, NULL);
|
|
}
|
|
def_c->remove(exp->var);
|
|
}
|
|
delete def_c;
|
|
}
|
|
|
|
pCommons->MarkAsUsed(c->graph->getUse(), c);
|
|
SgProcHedrStmt* header = isSgProcHedrStmt(c->header);
|
|
if (!header) {
|
|
is_correct = "no header for procedure";
|
|
failed_proc_name = c->funName;
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < GetNumberOfArguments(isFun, call); i++)
|
|
{
|
|
SgExpression* ar = GetProcedureArgument(isFun, call, i);
|
|
CArrayVarEntryInfo* tp = NULL;
|
|
if (c == (AnalysedCallsList*)(-1) || c == (AnalysedCallsList*)(-2) || c == NULL || c->graph == NULL || c->isArgIn(i, &tp))
|
|
addExprToUse(ar, tp);
|
|
tp = NULL;
|
|
if (c == (AnalysedCallsList*)(-1) || c == NULL || c->graph == NULL || c->isArgOut(i, &tp))
|
|
AddOneExpressionToDef(GetProcedureArgument(isFun, call, i), NULL, tp);
|
|
}
|
|
|
|
if (c != (AnalysedCallsList*)(-1) && c != (AnalysedCallsList*)(-2) && c != NULL && c->graph != NULL) {
|
|
for (CommonVarSet* cu = c->graph->getCommonUse(); cu != NULL; cu = cu->next) {
|
|
CommonVarInfo* v = cu->cvd;
|
|
AnalysedCallsList* tp = start->getProc();
|
|
CommonDataItem* p = v->parent;
|
|
if (CommonDataItem* it = pCommons->IsThisCommonUsedInProcedure(p, tp)) {
|
|
if (pCommons->CanHaveNonScalarVars(it))
|
|
continue;
|
|
CommonVarInfo* i = it->info;
|
|
CommonVarInfo* j = p->info;
|
|
while (j != v) {
|
|
j = j->next;
|
|
if (i)
|
|
i = i->next;
|
|
else
|
|
continue;
|
|
}
|
|
if (!i)
|
|
continue;
|
|
SgVarRefExp* var = new SgVarRefExp(i->var->GetSymbol());
|
|
addExprToUse(var);
|
|
}
|
|
else {
|
|
common_use = new CommonVarSet(*cu);
|
|
}
|
|
}
|
|
for (CommonVarSet* cd = c->graph->getCommonDef(); cd != NULL; cd = cd->next) {
|
|
CommonVarInfo* v = cd->cvd;
|
|
AnalysedCallsList* tp = start->getProc();
|
|
CommonDataItem* p = v->parent;
|
|
if (CommonDataItem* it = pCommons->IsThisCommonUsedInProcedure(p, tp)) {
|
|
if (pCommons->CanHaveNonScalarVars(it))
|
|
continue;
|
|
CommonVarInfo* i = it->info;
|
|
CommonVarInfo* j = p->info;
|
|
while (j != v) {
|
|
j = j->next;
|
|
if (i)
|
|
i = i->next;
|
|
}
|
|
if (!i)
|
|
continue;
|
|
def->addToSet(i->var, NULL);
|
|
}
|
|
else {
|
|
common_def = new CommonVarSet(*cd);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool CommonData::CanHaveNonScalarVars(CommonDataItem* item)
|
|
{
|
|
for (CommonDataItem* it = list; it != NULL; it = it->next) {
|
|
if (it->name == item->name && it->first == item->first && !it->onlyScalars)
|
|
return true;
|
|
}
|
|
bool res = !item->onlyScalars;
|
|
//printf("CommonData::CanHaveNonScalarVars: %d\n", res);
|
|
return res;
|
|
}
|
|
|
|
CommonDataItem* CommonData::IsThisCommonUsedInProcedure(CommonDataItem* item, AnalysedCallsList* p)
|
|
{
|
|
for (CommonDataItem* it = list; it != NULL; it = it->next) {
|
|
if (it->proc == p) {
|
|
if (it->name == item->name)
|
|
return it;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CBasicBlock::setDefAndUse()
|
|
{
|
|
ControlFlowItem* p = start;
|
|
while (p != NULL && (p == start || !p->isLeader()))
|
|
{
|
|
if (p->getJump() == NULL)
|
|
{
|
|
SgStatement* st = p->getStatement();
|
|
SgFunctionCallExp* f = p->getFunctionCall();
|
|
|
|
if (f != NULL)
|
|
{
|
|
bool add_intr = IsAnIntrinsicSubroutine(f->funName()->identifier()) != NULL; // strcmp(f->funName()->identifier(), "date_and_time") == 0;
|
|
bool intr = (isIntrinsicFunctionNameACC(f->funName()->identifier()) || add_intr) && !IsUserFunctionACC(f->funName());
|
|
bool pure = IsPureProcedureACC(f->funName());
|
|
AnalysedCallsList* c = p->getCall();
|
|
if (!intr && !pure && c && c != (AnalysedCallsList*)(-1) && c != (AnalysedCallsList*)(-2) && !(c->IsIntrinsic())) {
|
|
|
|
if (c->header == NULL) {
|
|
is_correct = "no header for procedure";
|
|
failed_proc_name = c->funName;
|
|
}
|
|
else {
|
|
//graph_node* oldgn = currentGraphNode;
|
|
//graph_node* newgn = GRAPHNODE(f->funName())->file_id;
|
|
//currentGraphNode = newgn;
|
|
ProcessUserProcedure(true, f, c);
|
|
//currentGraphNode = oldgn;
|
|
|
|
}
|
|
}
|
|
else if (c == (AnalysedCallsList*)(-1) || c == (AnalysedCallsList*)(-2))
|
|
ProcessProcedureWithoutBody(true, f, c == (AnalysedCallsList*)(-1));
|
|
else if (intr || (c && c->IsIntrinsic())) {
|
|
ProcessIntrinsicProcedure(true, f->numberOfArgs(), f, f->funName()->identifier());
|
|
}else
|
|
ProcessProcedureHeader(true, isSgProcHedrStmt(GRAPHNODE(f->funName())->st_header), f, f->funName()->identifier());
|
|
}
|
|
|
|
|
|
if (st != NULL)
|
|
{
|
|
switch (st->variant())
|
|
{
|
|
case ASSIGN_STAT:
|
|
{
|
|
SgAssignStmt* s = isSgAssignStmt(st);
|
|
SgExpression* l = s->lhs();
|
|
SgExpression* r = s->rhs();
|
|
addExprToUse(r);
|
|
AddOneExpressionToDef(l, st, NULL);
|
|
break;
|
|
}
|
|
case PRINT_STAT:
|
|
case WRITE_STAT:
|
|
case READ_STAT:
|
|
{
|
|
SgInputOutputStmt* s = isSgInputOutputStmt(st);
|
|
if (s) {
|
|
SgExpression* ex = s->itemList();
|
|
while (ex && ex->lhs()) {
|
|
if (st->variant() == READ_STAT) {
|
|
AddOneExpressionToDef(ex->lhs(), st, NULL);
|
|
}
|
|
else {
|
|
addExprToUse(ex->lhs());
|
|
}
|
|
ex = ex->rhs();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case PROC_STAT:
|
|
{
|
|
SgCallStmt* f = isSgCallStmt(st);
|
|
bool add_intr = IsAnIntrinsicSubroutine(f->name()->identifier()) != NULL;
|
|
bool intr = (isIntrinsicFunctionNameACC(f->name()->identifier()) || add_intr) && !IsUserFunctionACC(f->name());
|
|
bool pure = IsPureProcedureACC(f->name());
|
|
if (!intr && !pure) {
|
|
AnalysedCallsList* c = p->getCall();
|
|
//graph_node* oldgn = currentGraphNode;
|
|
//graph_node* newgn = GRAPHNODE(f->name());
|
|
//currentGraphNode = newgn;
|
|
ProcessUserProcedure(false, f, c);
|
|
//currentGraphNode = oldgn;
|
|
break;
|
|
}
|
|
if (intr) {
|
|
ProcessIntrinsicProcedure(false, f->numberOfArgs(), f, f->name()->identifier());
|
|
break;
|
|
}
|
|
ProcessProcedureHeader(false, isSgProcHedrStmt(GRAPHNODE(f->name())->st_header), f, f->name()->identifier());
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
addExprToUse(p->getExpression());
|
|
p = p->getNext();
|
|
}
|
|
}
|
|
|
|
VarSet* CBasicBlock::getDef()
|
|
{
|
|
if (def == NULL)
|
|
{
|
|
def = new VarSet();
|
|
use = new VarSet();
|
|
setDefAndUse();
|
|
}
|
|
return def;
|
|
}
|
|
|
|
VarSet* CBasicBlock::getUse()
|
|
{
|
|
if (use == NULL)
|
|
{
|
|
use = new VarSet();
|
|
def = new VarSet();
|
|
setDefAndUse();
|
|
}
|
|
return use;
|
|
}
|
|
|
|
#ifdef __SPF
|
|
template<typename IN_TYPE, typename OUT_TYPE>
|
|
const vector<OUT_TYPE> getAttributes(IN_TYPE st, const set<int> dataType);
|
|
#endif
|
|
|
|
DoLoopDataItem* DoLoopDataList::FindLoop(SgStatement* st)
|
|
{
|
|
DoLoopDataItem* it = list;
|
|
while (it != NULL) {
|
|
if (it->statement == st)
|
|
return it;
|
|
it = it->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool GetExpressionAndCoefficientOfBound(SgExpression* exp, SgExpression** end, int* coef)
|
|
{
|
|
if (exp->variant() == SUBT_OP) {
|
|
if (exp->rhs() && exp->rhs()->variant() == INT_VAL) {
|
|
*end = exp->lhs();
|
|
*coef = -exp->rhs()->valueInteger();
|
|
return true;
|
|
}
|
|
}
|
|
if (exp->variant() == ADD_OP) {
|
|
if (exp->lhs() && exp->lhs()->variant() == INT_VAL) {
|
|
*end = exp->rhs();
|
|
*coef = exp->lhs()->valueInteger();
|
|
return true;
|
|
}
|
|
if (exp->rhs() && exp->rhs()->variant() == INT_VAL) {
|
|
*end = exp->lhs();
|
|
*coef = exp->lhs()->valueInteger();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CArrayVarEntryInfo::CArrayVarEntryInfo(SgSymbol* s, SgArrayRefExp* r) : CVarEntryInfo(s)
|
|
{
|
|
#if __SPF
|
|
addToCollection(__LINE__, __FILE__, this, 16);
|
|
#endif
|
|
// TODO: need to check all alhorithm!!
|
|
disabled = true;
|
|
|
|
if (!r)
|
|
subscripts = 0;
|
|
else
|
|
subscripts = r->numberOfSubscripts();
|
|
if (subscripts)
|
|
data.resize(subscripts);
|
|
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
data[i].defined = false;
|
|
data[i].bound_modifiers[0] = data[i].bound_modifiers[1] = 0;
|
|
data[i].step = 1;
|
|
data[i].left_bound = data[i].right_bound = NULL;
|
|
data[i].coefs[0] = data[i].coefs[1] = 0;
|
|
data[i].loop = NULL;
|
|
#if __SPF
|
|
const vector<int*> coefs = getAttributes<SgExpression*, int*>(r->subscript(i), set<int>{ INT_VAL });
|
|
const vector<SgStatement*> fs = getAttributes<SgExpression*, SgStatement*>(r->subscript(i), set<int>{ FOR_NODE });
|
|
if (fs.size() == 1)
|
|
{
|
|
if (data[i].loop != NULL)
|
|
{
|
|
if (coefs.size() == 1)
|
|
{
|
|
data[i].defined = true;
|
|
data[i].bound_modifiers[0] = data[i].bound_modifiers[1] = coefs[0][1];
|
|
data[i].coefs[0] = coefs[0][0];
|
|
data[i].coefs[1] = coefs[0][1];
|
|
data[i].step = coefs[0][0];
|
|
int tmp;
|
|
|
|
SgExpression *et;
|
|
if (GetExpressionAndCoefficientOfBound(data[i].loop->l, &et, &tmp))
|
|
{
|
|
data[i].left_bound = et;
|
|
data[i].bound_modifiers[0] += tmp;
|
|
}
|
|
else
|
|
data[i].left_bound = data[i].loop->l;
|
|
|
|
if (GetExpressionAndCoefficientOfBound(data[i].loop->r, &et, &tmp))
|
|
{
|
|
data[i].right_bound = et;
|
|
data[i].bound_modifiers[1] += tmp;
|
|
}
|
|
else
|
|
data[i].right_bound = data[i].loop->r;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if (!data[i].defined)
|
|
{
|
|
SgExpression* ex = r->subscript(i);
|
|
if (ex->variant() == INT_VAL)
|
|
{
|
|
data[i].bound_modifiers[0] = ex->valueInteger();
|
|
data[i].bound_modifiers[1] = ex->valueInteger();
|
|
data[i].defined = true;
|
|
}
|
|
else
|
|
{
|
|
data[i].bound_modifiers[0] = 0;
|
|
data[i].bound_modifiers[1] = 0;
|
|
data[i].left_bound = data[i].right_bound = ex;
|
|
data[i].defined = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CArrayVarEntryInfo::CArrayVarEntryInfo(SgSymbol *s, int sub, int ds, const vector<ArraySubscriptData> &d)
|
|
: CVarEntryInfo(s), subscripts(sub), disabled(ds)
|
|
{
|
|
#if __SPF
|
|
addToCollection(__LINE__, __FILE__, this, 16);
|
|
#endif
|
|
if (sub > 0)
|
|
data = d;
|
|
}
|
|
|
|
VarItem* VarSet::GetArrayRef(CArrayVarEntryInfo* info)
|
|
{
|
|
VarItem* it = list;
|
|
while (it != NULL) {
|
|
CVarEntryInfo* v = it->var;
|
|
if (v->GetVarType() == VAR_REF_ARRAY_EXP) {
|
|
if (OriginalSymbol(info->GetSymbol()) == OriginalSymbol(v->GetSymbol()))
|
|
return it;
|
|
}
|
|
it = it->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CArrayVarEntryInfo::RegisterUsage(VarSet *def, VarSet *use, SgStatement *st)
|
|
{
|
|
VarItem *it = def->GetArrayRef(this);
|
|
CArrayVarEntryInfo *add = this;
|
|
if (it != NULL)
|
|
add = *this - *(CArrayVarEntryInfo*)(it->var);
|
|
|
|
if (use != NULL && add != NULL && add->HasActiveElements())
|
|
use->addToSet(add, st);
|
|
|
|
if (add != this)
|
|
delete add;
|
|
}
|
|
|
|
CArrayVarEntryInfo& CArrayVarEntryInfo::operator-=(const CArrayVarEntryInfo& b)
|
|
{
|
|
if (subscripts == 0)
|
|
{
|
|
if (b.HasActiveElements())
|
|
disabled = true;
|
|
return *this;
|
|
}
|
|
|
|
if (b.subscripts == 0)
|
|
{
|
|
if (HasActiveElements())
|
|
MakeInactive();
|
|
return *this;
|
|
}
|
|
|
|
if (subscripts != b.subscripts || !data.size() || !b.data.size() || !(data[0].defined) || !(b.data[0].defined))
|
|
return *this;
|
|
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
if (b.data[i].left_bound == NULL)
|
|
{
|
|
if (data[i].left_bound && data[i].left_bound->variant() == INT_VAL)
|
|
{
|
|
if (data[i].left_bound->valueInteger() + data[i].bound_modifiers[0] == b.data[i].bound_modifiers[0])
|
|
{
|
|
data[i].bound_modifiers[0]++;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (data[i].left_bound == NULL && b.data[i].left_bound == NULL &&
|
|
data[i].right_bound == NULL && b.data[i].right_bound == NULL)
|
|
{
|
|
if (data[i].bound_modifiers[0] < b.data[i].bound_modifiers[0])
|
|
{
|
|
data[i].bound_modifiers[1] = b.data[i].bound_modifiers[0] - 1;
|
|
continue;
|
|
}
|
|
|
|
if (data[i].bound_modifiers[1] > b.data[i].bound_modifiers[1])
|
|
{
|
|
data[i].bound_modifiers[0] = b.data[i].bound_modifiers[1] + 1;
|
|
continue;
|
|
}
|
|
data[i].defined = false;
|
|
}
|
|
|
|
if (data[i].left_bound == b.data[i].left_bound && data[i].bound_modifiers[0] < b.data[i].bound_modifiers[0])
|
|
{
|
|
data[i].bound_modifiers[0] = data[i].bound_modifiers[0];
|
|
data[i].bound_modifiers[1] = b.data[i].bound_modifiers[0] - 1;
|
|
data[i].right_bound = data[i].left_bound;
|
|
}
|
|
|
|
if (data[i].right_bound == b.data[i].right_bound && data[i].bound_modifiers[1] > b.data[i].bound_modifiers[1])
|
|
{
|
|
data[i].bound_modifiers[0] = b.data[i].bound_modifiers[1] + 1;
|
|
data[i].bound_modifiers[1] = data[i].bound_modifiers[1];
|
|
data[i].left_bound = data[i].right_bound;
|
|
}
|
|
|
|
if (b.data[i].left_bound == NULL && b.data[i].right_bound == NULL &&
|
|
(data[i].left_bound != NULL || data[i].right_bound != NULL))
|
|
continue;
|
|
else
|
|
{
|
|
data[i].bound_modifiers[0] = data[i].bound_modifiers[1] = 0;
|
|
data[i].left_bound = NULL;
|
|
data[i].right_bound = NULL;
|
|
data[i].defined = false;
|
|
//empty set
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
CArrayVarEntryInfo* operator-(const CArrayVarEntryInfo& a, const CArrayVarEntryInfo& b)
|
|
{
|
|
//return NULL;
|
|
CArrayVarEntryInfo* nv = (CArrayVarEntryInfo*)a.Clone();
|
|
*nv -= b;
|
|
return nv;
|
|
}
|
|
|
|
CArrayVarEntryInfo* operator+(const CArrayVarEntryInfo& a, const CArrayVarEntryInfo& b)
|
|
{
|
|
CArrayVarEntryInfo* nv = (CArrayVarEntryInfo*)a.Clone();
|
|
*nv += b;
|
|
return nv;
|
|
}
|
|
|
|
void CArrayVarEntryInfo::RegisterDefinition(VarSet* def, VarSet* use, SgStatement* st)
|
|
{
|
|
def->addToSet(this, st);
|
|
use->PossiblyAffectArrayEntry(this);
|
|
}
|
|
|
|
void VarSet::PossiblyAffectArrayEntry(CArrayVarEntryInfo* var)
|
|
{
|
|
VarItem* it = GetArrayRef(var);
|
|
if (!it)
|
|
return;
|
|
((CArrayVarEntryInfo*)(it->var))->ProcessChangesToUsedEntry(var);
|
|
}
|
|
|
|
void CArrayVarEntryInfo::ProcessChangesToUsedEntry(CArrayVarEntryInfo* var)
|
|
{
|
|
if (disabled || var->disabled || subscripts != var->subscripts)
|
|
return;
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
if (!data[i].defined)
|
|
continue;
|
|
|
|
if (data[i].loop == var->data[i].loop && data[i].loop != NULL)
|
|
{
|
|
if (data[i].coefs[0] == var->data[i].coefs[0])
|
|
{
|
|
if (data[i].coefs[1] < var->data[i].coefs[1])
|
|
{
|
|
if (data[i].left_bound && data[i].left_bound->variant() == INT_VAL)
|
|
{
|
|
data[i].bound_modifiers[0] = data[i].left_bound->valueInteger() + data[i].bound_modifiers[0];
|
|
data[i].bound_modifiers[1] = data[i].left_bound->valueInteger() + var->data[i].coefs[1] - 1;
|
|
data[i].left_bound = data[i].right_bound = NULL;
|
|
}
|
|
else
|
|
{
|
|
//maybe add something, not sure
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CArrayVarEntryInfo& CArrayVarEntryInfo::operator*=(const CArrayVarEntryInfo& b)
|
|
{
|
|
if (subscripts == 0)
|
|
{
|
|
if (b.HasActiveElements())
|
|
disabled = true;
|
|
return *this;
|
|
}
|
|
|
|
if (b.subscripts == 0)
|
|
{
|
|
if (HasActiveElements())
|
|
MakeInactive();
|
|
return *this;
|
|
}
|
|
|
|
//return *this;
|
|
if (subscripts != b.subscripts || subscripts == 0 || b.subscripts == 0 || !data.size() || !b.data.size() || !(data[0].defined) || !(b.data[0].defined))
|
|
return *this;
|
|
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
if (b.disabled)
|
|
data[i].left_bound = data[i].right_bound = NULL;
|
|
|
|
if (data[i].left_bound == b.data[i].left_bound)
|
|
data[i].bound_modifiers[0] = std::max(data[i].bound_modifiers[0], b.data[i].bound_modifiers[0]);
|
|
|
|
if (data[i].right_bound == b.data[i].right_bound)
|
|
data[i].bound_modifiers[1] = std::min(data[i].bound_modifiers[1], b.data[i].bound_modifiers[1]);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
CArrayVarEntryInfo& CArrayVarEntryInfo::operator+=(const CArrayVarEntryInfo& b)
|
|
{
|
|
if (subscripts == 0)
|
|
{
|
|
if (b.HasActiveElements())
|
|
disabled = true;
|
|
return *this;
|
|
}
|
|
|
|
if (b.subscripts == 0)
|
|
{
|
|
if (HasActiveElements())
|
|
MakeInactive();
|
|
return *this;
|
|
}
|
|
|
|
//return *this;
|
|
if (disabled && !b.disabled && b.data.size())
|
|
{
|
|
for (int i = 0; i < subscripts; i++)
|
|
data[i] = b.data[i];
|
|
disabled = false;
|
|
return *this;
|
|
}
|
|
|
|
if (subscripts != b.subscripts || subscripts == 0 || b.subscripts == 0 || !data.size() || !b.data.size() || disabled || b.disabled)
|
|
return *this;
|
|
|
|
for (int i = 0; i < subscripts; i++)
|
|
{
|
|
|
|
if (data[i].left_bound == b.data[i].left_bound)
|
|
data[i].bound_modifiers[0] = std::min(data[i].bound_modifiers[0], b.data[i].bound_modifiers[0]);
|
|
|
|
if (data[i].right_bound == b.data[i].right_bound)
|
|
data[i].bound_modifiers[1] = std::max(data[i].bound_modifiers[1], b.data[i].bound_modifiers[1]);
|
|
|
|
if (data[i].left_bound == NULL && data[i].right_bound == NULL && (b.data[i].left_bound != NULL || b.data[i].right_bound != NULL))
|
|
{
|
|
const ArraySubscriptData &tmp = data[i];
|
|
data[i] = b.data[i];
|
|
if (data[i].left_bound && data[i].left_bound->variant() == INT_VAL)
|
|
{
|
|
if (tmp.bound_modifiers[1] == data[i].left_bound->valueInteger() + data[i].bound_modifiers[0] - 1)
|
|
data[i].bound_modifiers[0] -= (1 + tmp.bound_modifiers[1] - tmp.bound_modifiers[0]);
|
|
|
|
}
|
|
|
|
if (data[i].right_bound && data[i].right_bound->variant() == INT_VAL)
|
|
{
|
|
if (tmp.bound_modifiers[0] == data[i].left_bound->valueInteger() + data[i].bound_modifiers[1] + 1)
|
|
data[i].bound_modifiers[1] += (1 + tmp.bound_modifiers[1] - tmp.bound_modifiers[0]);
|
|
}
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void VarSet::RemoveDoubtfulCommonVars(AnalysedCallsList* call)
|
|
{
|
|
VarItem* it = list;
|
|
VarItem* prev = NULL;
|
|
while (it != NULL) {
|
|
CommonDataItem* d = pCommons->IsThisCommonVar(it, call);
|
|
if (d && pCommons->CanHaveNonScalarVars(d)) {
|
|
if (prev == NULL) {
|
|
it = it->next;
|
|
delete list;
|
|
list = it;
|
|
}
|
|
else {
|
|
prev->next = it->next;
|
|
delete it;
|
|
it = prev->next;
|
|
}
|
|
continue;
|
|
}
|
|
prev = it;
|
|
it = it->next;
|
|
}
|
|
}
|
|
|
|
int VarSet::count()
|
|
{
|
|
VarItem* it = list;
|
|
int t = 0;
|
|
while (it != NULL) {
|
|
it = it->next;
|
|
t++;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
void VarSet::LeaveOnlyRecords()
|
|
{
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL) {
|
|
if (p->var->GetVarType() == VAR_REF_RECORD_EXP) {
|
|
CVarEntryInfo* rrec = p->var->GetLeftmostParent();
|
|
CVarEntryInfo* old = p->var;
|
|
if (old->RemoveReference())
|
|
delete old;
|
|
if (!belongs(rrec)) {
|
|
p->var = rrec;
|
|
prev = p;
|
|
}
|
|
else {
|
|
if (prev == NULL)
|
|
list = list->next;
|
|
else
|
|
{
|
|
prev->next = p->next;
|
|
delete(p);
|
|
p = prev;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
prev = p;
|
|
}
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
VarItem* VarSet::belongs(const CVarEntryInfo* var, bool os)
|
|
{
|
|
VarItem* l = list;
|
|
while (l != NULL)
|
|
{
|
|
if ((*l->var == *var))
|
|
return l;
|
|
if (os && OriginalSymbol(l->var->GetSymbol()) == OriginalSymbol(var->GetSymbol()))
|
|
return l;
|
|
l = l->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
VarItem* VarSet::belongs(SgSymbol* s, bool os)
|
|
{
|
|
VarItem* l = list;
|
|
while (l != NULL)
|
|
{
|
|
if ((l->var->GetSymbol() == s))
|
|
if (l->var->GetVarType() == VAR_REF_ARRAY_EXP)
|
|
return ((CArrayVarEntryInfo*)(l->var))->HasActiveElements() ? l : NULL;
|
|
return l;
|
|
if (os && OriginalSymbol(l->var->GetSymbol()) == OriginalSymbol(s))
|
|
return l;
|
|
l = l->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
VarItem* VarSet::belongs(SgVarRefExp* var, bool os)
|
|
{
|
|
return belongs(var->symbol(), os);
|
|
}
|
|
*/
|
|
|
|
bool VarSet::equal(VarSet* p2)
|
|
{
|
|
if (p2 == NULL)
|
|
return false;
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL)
|
|
{
|
|
if (!p2->belongs(p->var) && (p->var->GetVarType() != VAR_REF_ARRAY_EXP || ((CArrayVarEntryInfo*)(p->var))->HasActiveElements()))
|
|
return false;
|
|
p = p->next;
|
|
}
|
|
p = p2->list;
|
|
while (p != NULL) {
|
|
if (!belongs(p->var) && (p->var->GetVarType() != VAR_REF_ARRAY_EXP || ((CArrayVarEntryInfo*)(p->var))->HasActiveElements()))
|
|
return false;
|
|
p = p->next;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void VarSet::print()
|
|
{
|
|
VarItem* l = list;
|
|
while (l != NULL)
|
|
{
|
|
if (l->var->GetVarType() != VAR_REF_ARRAY_EXP || ((CArrayVarEntryInfo*)(l->var))->HasActiveElements())
|
|
printf("%s ", l->var->GetSymbol()->identifier());
|
|
#if PRIVATE_GET_LAST_ASSIGN
|
|
printf("last assignments: %d\n", l->lastAssignments.size());
|
|
for (list<SgStatement*>::iterator it = l->lastAssignments.begin(); it != l->lastAssignments.end(); it++){
|
|
if (*it)
|
|
printf("%s", (*it)->unparse());
|
|
}
|
|
#endif
|
|
l = l->next;
|
|
}
|
|
putchar('\n');
|
|
}
|
|
|
|
void VarSet::addToSet(CVarEntryInfo* var, SgStatement* source, CVarEntryInfo* ov)
|
|
{
|
|
bool add = false;
|
|
if (var->GetVarType() != VAR_REF_ARRAY_EXP) {
|
|
VarItem* p = belongs(var, false);
|
|
add = p == NULL;
|
|
#if PRIVATE_GET_LAST_ASSIGN
|
|
p->lastAssignments.clear();
|
|
p->lastAssignments.push_back(source);
|
|
#endif
|
|
//delete p->lastAssignments;
|
|
//p->lastAssignments = new CLAStatementItem();
|
|
//p->lastAssignments->stmt = source;
|
|
//p->lastAssignments->next = NULL;
|
|
}
|
|
else {
|
|
CArrayVarEntryInfo* av = (CArrayVarEntryInfo*)var;
|
|
VarItem* p = GetArrayRef(av);
|
|
if (p == NULL)
|
|
add = true;
|
|
else {
|
|
CArrayVarEntryInfo* fv = (CArrayVarEntryInfo*)p->var;
|
|
*fv += *av;
|
|
}
|
|
}
|
|
if (add) {
|
|
VarItem* p = new VarItem();
|
|
p->var = var->Clone();
|
|
p->ov = ov;
|
|
p->next = list;
|
|
p->file_id = current_file_id;
|
|
list = p;
|
|
}
|
|
}
|
|
|
|
void VarSet::intersect(VarSet* set, bool la, bool array_mode = false)
|
|
{
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL)
|
|
{
|
|
VarItem* n = set->belongs(p->var);
|
|
if (!n)
|
|
{
|
|
if (!array_mode || p->var->GetVarType() == VAR_REF_VAR_EXP) {
|
|
if (prev == NULL)
|
|
list = list->next;
|
|
else
|
|
{
|
|
prev->next = p->next;
|
|
delete(p);
|
|
p = prev;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
#if PRIVATE_GET_LAST_ASSIGN
|
|
if (la)
|
|
p->lastAssignments.insert(p->lastAssignments.end(), n->lastAssignments.begin(), n->lastAssignments.end());
|
|
#endif
|
|
if (p->var->GetVarType() == VAR_REF_ARRAY_EXP) {
|
|
if (!array_mode)
|
|
*(CArrayVarEntryInfo*)(p->var) *= *(CArrayVarEntryInfo*)(n->var);
|
|
else
|
|
*(CArrayVarEntryInfo*)(p->var) += *(CArrayVarEntryInfo*)(n->var);
|
|
}
|
|
prev = p;
|
|
}
|
|
p = p->next;
|
|
}
|
|
|
|
}
|
|
|
|
VarItem* VarSet::getFirst()
|
|
{
|
|
return list;
|
|
}
|
|
|
|
void VarSet::remove(const CVarEntryInfo* var)
|
|
{
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL)
|
|
{
|
|
if (var == (p->var))
|
|
{
|
|
if (prev == NULL) {
|
|
VarItem* t = list;
|
|
list = list->next;
|
|
delete(t);
|
|
p = list;
|
|
|
|
}
|
|
else
|
|
{
|
|
prev->next = p->next;
|
|
delete(p);
|
|
p = prev->next;
|
|
}
|
|
}
|
|
else {
|
|
prev = p;
|
|
p = p->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void VarSet::minus(VarSet* set, bool complete)
|
|
{
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL)
|
|
{
|
|
VarItem* d = set->belongs(p->var);
|
|
if (d && (p->var->GetVarType() != VAR_REF_ARRAY_EXP || ((CArrayVarEntryInfo*)(d->var))->HasActiveElements()))
|
|
{
|
|
if (p->var->GetVarType() == VAR_REF_ARRAY_EXP && !complete) {
|
|
*(CArrayVarEntryInfo*)(p->var) -= *(CArrayVarEntryInfo*)(d->var);
|
|
prev = p;
|
|
}
|
|
else if (prev == NULL)
|
|
list = list->next;
|
|
else
|
|
{
|
|
prev->next = p->next;
|
|
delete(p);
|
|
p = prev;
|
|
}
|
|
}
|
|
else
|
|
prev = p;
|
|
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
bool VarSet::RecordBelong(CVarEntryInfo* rec)
|
|
{
|
|
if (rec->GetVarType() != VAR_REF_RECORD_EXP)
|
|
return false;
|
|
CRecordVarEntryInfo* rrec = static_cast<CRecordVarEntryInfo*>(rec);
|
|
CVarEntryInfo* lm = rrec->GetLeftmostParent();
|
|
VarItem* p = list;
|
|
while (p != NULL) {
|
|
if (*lm == *(p->var->GetLeftmostParent()))
|
|
return true;
|
|
p = p->next;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void VarSet::minusFinalize(VarSet* set, bool complete)
|
|
{
|
|
minus(set, complete);
|
|
VarItem* p = list;
|
|
VarItem* prev = NULL;
|
|
while (p != NULL)
|
|
{
|
|
if (set->RecordBelong(p->var)) {
|
|
{
|
|
if (prev == NULL)
|
|
list = list->next;
|
|
else
|
|
{
|
|
prev->next = p->next;
|
|
delete(p);
|
|
p = prev;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
prev = p;
|
|
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
unsigned int counter = 0;
|
|
|
|
CLAStatementItem::~CLAStatementItem()
|
|
{
|
|
#if __SPF
|
|
removeFromCollection(this);
|
|
#endif
|
|
if (next)
|
|
delete next;
|
|
}
|
|
|
|
CLAStatementItem* CLAStatementItem::GetLast()
|
|
{
|
|
if (next == NULL)
|
|
return this;
|
|
return next->GetLast();
|
|
}
|
|
|
|
void VarSet::unite(VarSet* set, bool la)
|
|
{
|
|
VarItem* arg2 = set->list;
|
|
while (arg2 != NULL)
|
|
{
|
|
VarItem* n = belongs(arg2->var);
|
|
if (!n)
|
|
{
|
|
n = new VarItem();
|
|
if (arg2->var->GetVarType() == VAR_REF_ARRAY_EXP)
|
|
n->var = arg2->var->Clone();
|
|
else {
|
|
n->var = arg2->var;
|
|
n->var->AddReference();
|
|
}
|
|
n->ov = arg2->ov;
|
|
n->next = list;
|
|
n->file_id = arg2->file_id;
|
|
#if PRIVATE_GET_LAST_ASSIGN
|
|
if (la)
|
|
n->lastAssignments = arg2->lastAssignments;
|
|
#endif
|
|
list = n;
|
|
}
|
|
else {
|
|
#if PRIVATE_GET_LAST_ASSIGN
|
|
if (la) {
|
|
//n->lastAssignments.insert(n->lastAssignments.end(), arg2->lastAssignments.begin(), arg2->lastAssignments.end());
|
|
//n->lastAssignments.splice(n->lastAssignments.end(), arg2->lastAssignments);
|
|
//n->lastAssignments->GetLast()->next = arg2->lastAssignments;
|
|
n->lastAssignments = arg2->lastAssignments;
|
|
}
|
|
#endif
|
|
//counter++;
|
|
//if (counter % 100 == 0)
|
|
//printf("%d!\n", counter);
|
|
if (n->var->GetVarType() == VAR_REF_ARRAY_EXP) {
|
|
*(CArrayVarEntryInfo*)(n->var) += *(CArrayVarEntryInfo*)(arg2->var);
|
|
}
|
|
}
|
|
arg2 = arg2->next;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CBasicBlock::addToPrev(CBasicBlock* bb, bool for_jump_flag, bool c, ControlFlowItem* check)
|
|
{
|
|
BasicBlockItem* n = new BasicBlockItem();
|
|
n->block = bb;
|
|
n->next = prev;
|
|
n->for_jump_flag = for_jump_flag;
|
|
n->cond_value = c;
|
|
n->jmp = check;
|
|
prev = n;
|
|
}
|
|
|
|
void CBasicBlock::addToSucc(CBasicBlock* bb, bool for_jump_flag, bool c, ControlFlowItem* check)
|
|
{
|
|
BasicBlockItem* n = new BasicBlockItem();
|
|
n->block = bb;
|
|
n->for_jump_flag = for_jump_flag;
|
|
n->next = succ;
|
|
n->cond_value = c;
|
|
n->jmp = check;
|
|
succ = n;
|
|
}
|
|
|
|
#if ACCAN_DEBUG
|
|
|
|
void ControlFlowItem::printDebugInfo()
|
|
{
|
|
if (jmp == NULL && stmt == NULL && func != NULL)
|
|
printf("FUNCTION CALL: %s\n", func->unparse());
|
|
if (jmp == NULL)
|
|
if (stmt != NULL)
|
|
if (label != NULL)
|
|
printf("%d: %s %s %s lab %4d %s", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", label->id(), stmt->unparse());
|
|
else
|
|
printf("%d: %s %s %s %s", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", stmt->unparse());
|
|
else
|
|
if (label != NULL)
|
|
printf("%d: %s %s %s lab %4d \n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", label->id());
|
|
else
|
|
printf("%d: %s %s %s \n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ");
|
|
else
|
|
if (expr == NULL)
|
|
if (label != NULL)
|
|
printf("%d: %s %s %s lab %4d goto %d\n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", label->id(), jmp->getStmtNo());
|
|
else
|
|
printf("%d: %s %s %s goto %d\n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", jmp->getStmtNo());
|
|
else
|
|
if (label != NULL)
|
|
printf("%d: %s %s %s lab %4d if %s goto %d\n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", label->id(), expr->unparse(), jmp->getStmtNo());
|
|
else
|
|
printf("%d: %s %s %s if %s goto %d\n", stmtNo, this->isLeader() ? "L" : " ", this->IsParloopStart() ? "S" : " ", this->IsParloopEnd() ? "E" : " ", expr->unparse(), jmp->getStmtNo());
|
|
}
|
|
|
|
static void printControlFlowList(ControlFlowItem* list, ControlFlowItem* last)
|
|
{
|
|
|
|
printf("DEBUG PRINT START\n");
|
|
unsigned int stmtNo = 0;
|
|
ControlFlowItem* list_copy = list;
|
|
while (list != NULL )
|
|
{
|
|
list->setStmtNo(++stmtNo);
|
|
if (list == last)
|
|
break;
|
|
list = list->getNext();
|
|
}
|
|
|
|
list = list_copy;
|
|
while (list != NULL)
|
|
{
|
|
list->printDebugInfo();
|
|
if (list == last)
|
|
break;
|
|
list = list->getNext();
|
|
}
|
|
printf("DEBUG PRINT END\n\n");
|
|
}
|
|
#endif
|
|
|
|
void CallData::printControlFlows()
|
|
{
|
|
#if ACCAN_DEBUG
|
|
AnalysedCallsList* l = calls_list;
|
|
while (l != NULL) {
|
|
if (!l->isIntrinsic && l->graph != NULL && l->header != NULL) {
|
|
ControlFlowGraph* g = l->graph;
|
|
SgStatement* h = l->header;
|
|
printf("CFI for %s\n\n" ,h->symbol()->identifier());
|
|
if (g != NULL) {
|
|
printControlFlowList(g->getCFI());
|
|
}
|
|
else
|
|
printf("ERROR: DOES NOT HAVE CFI\n");
|
|
}
|
|
l = l->next;
|
|
}
|
|
#endif
|
|
}
|