Files
SAPFOR/dvm/fdvm/trunk/fdvm/acc_analyzer.cpp
2023-09-14 19:43:13 +03:00

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
}