moved
This commit is contained in:
357
Sapfor/_src/DynamicAnalysis/createParallelRegions.cpp
Normal file
357
Sapfor/_src/DynamicAnalysis/createParallelRegions.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
#include "dvm.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "./createParallelRegions.h"
|
||||
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "./gcov_info.h"
|
||||
#include "./gCov_parser_func.h"
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::stack;
|
||||
using std::pair;
|
||||
using std::to_string;
|
||||
|
||||
static void markNestedIntervals(SpfInterval *interval)
|
||||
{
|
||||
for (auto &item : interval->nested)
|
||||
{
|
||||
item->isNested = true;
|
||||
|
||||
if (!item->begin->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (item->begin->symbol()->identifier() != NULL)
|
||||
markNestedIntervals(item);
|
||||
}
|
||||
}
|
||||
|
||||
static int countOfIntervals(const SpfInterval *interval, const SpfInterval *mainInterval)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto &item : mainInterval->nested)
|
||||
{
|
||||
if (item == interval)
|
||||
count++;
|
||||
else
|
||||
count += countOfIntervals(interval, item);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void performFuncTime(const map<string, vector<FuncInfo*>> &funcInfo, map<string, int> &countFunc)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto &str : funcInfo)
|
||||
{
|
||||
count = 0;
|
||||
for (auto *info : str.second)
|
||||
{
|
||||
count += (info->callsTo).size();
|
||||
|
||||
if (countFunc.find(info->funcName) != countFunc.end())
|
||||
countFunc[info->funcName] += count;
|
||||
else
|
||||
countFunc.insert(make_pair(info->funcName, count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double performTime(SgProject* project, SgStatement *src, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls, int recLevel)
|
||||
{
|
||||
SgStatement* stmt = src;
|
||||
|
||||
if (!src->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (!isSgExecutableStatement(stmt))
|
||||
return 0.0;
|
||||
|
||||
auto gCovForFile = gCovInfo.find(string(stmt->fileName()));
|
||||
if (gCovForFile == gCovInfo.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto gCovForStmt = gCovForFile->second.find(stmt->lineNumber());
|
||||
if (gCovForStmt == gCovForFile->second.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const Gcov_info& info = gCovForStmt->second;
|
||||
double count = 0.0;
|
||||
|
||||
switch (stmt->variant())
|
||||
{
|
||||
case PROC_STAT:
|
||||
{
|
||||
if (recLevel <= 5)
|
||||
{
|
||||
SgCallStmt *call = (SgCallStmt*)src;
|
||||
if (info.getCountCalls() == 0)
|
||||
break;
|
||||
SgStatement *body = NULL;
|
||||
string funcName(call->name()->identifier());
|
||||
auto num = calls.find(funcName);
|
||||
// its not a user function
|
||||
if (num == calls.end())
|
||||
break;
|
||||
|
||||
for (int j = 0; j < project->numberOfFiles(); ++j)
|
||||
{
|
||||
SgFile& file = project->file(j);
|
||||
if (SgFile::switchToFile(file.filename()) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < file.numberOfFunctions(); ++i)
|
||||
{
|
||||
if (!strcmp(file.functions(i)->symbol()->identifier(), funcName.c_str()))
|
||||
{
|
||||
body = file.functions(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (body == NULL)
|
||||
break;
|
||||
|
||||
while (body && body->variant() != RETURN_STAT)
|
||||
{
|
||||
count += performTime(project, body, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!body->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
body = body->lexNext();
|
||||
}
|
||||
|
||||
count /= num->second;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IF_NODE:
|
||||
case LOGIF_NODE:
|
||||
case ELSEIF_NODE:
|
||||
{
|
||||
SgIfStmt* ifSt = (SgIfStmt*)src;
|
||||
SgStatement* tmp = ifSt->trueBody();
|
||||
int t = 0;
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
count += (info.getBranches()[0].getPercent()) * 0.01 * t;
|
||||
t = 0;
|
||||
tmp = ifSt->falseBody();
|
||||
while (tmp && tmp->variant() != CONTROL_END)
|
||||
{
|
||||
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
count += (info.getBranches()[1].getPercent()) * 0.01 * t;
|
||||
break;
|
||||
}
|
||||
case WHILE_NODE:
|
||||
{
|
||||
SgWhileStmt* whileSt = (SgWhileStmt*)src;
|
||||
SgStatement* tmp = whileSt->body();
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!tmp->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FOR_NODE:
|
||||
{
|
||||
SgForStmt* forSt = (SgForStmt*)src;
|
||||
SgStatement* tmp = forSt->body();
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!tmp->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADD_OP:
|
||||
case MULT_OP:
|
||||
case DIV_OP:
|
||||
case SUB_OP:
|
||||
case ASSGN_OP:
|
||||
case ASSIGN_STAT:
|
||||
// let frequency be about 2 GHerz
|
||||
count += 0.0000000005 * info.getExecutedCount();
|
||||
break;
|
||||
case WRITE_STAT:
|
||||
case READ_STAT:
|
||||
// read/write operations are slower
|
||||
count += 0.0000000015 * info.getExecutedCount();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
typedef pair<vector<SpfInterval*>, int> PositionInVector;
|
||||
typedef stack<PositionInVector> IntervalStack;
|
||||
|
||||
double performIntervalTime(SgProject* project, const SpfInterval *interval, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls)
|
||||
{
|
||||
double time = 0.0;
|
||||
for (SgStatement *stat = interval->begin; stat != interval->ends[interval->ends.size() - 1]; stat = stat->lexNext())
|
||||
{
|
||||
time += performTime(project, stat, gCovInfo, calls, 0);
|
||||
if (!stat->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void createParallelRegions(SgProject* project, SpfInterval *mainInterval, const map<string, map<int, Gcov_info>> &gCovInfo, const map<string, vector<FuncInfo*>> &funcInfo)
|
||||
{
|
||||
double percent = 0.8;
|
||||
vector<SpfRegion> regions;
|
||||
map<string, int> calls;
|
||||
|
||||
performFuncTime(funcInfo, calls);
|
||||
if (mainInterval == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, directives will not be generated for this file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
double sumTime = performIntervalTime(project, mainInterval, gCovInfo, calls);
|
||||
|
||||
double alreadyHavePercent = 0.0;
|
||||
int id = 1;
|
||||
int i = 0;
|
||||
IntervalStack stack;
|
||||
vector<SpfInterval*> iterated;
|
||||
vector<SpfInterval*> nested;
|
||||
|
||||
iterated.push_back(mainInterval);
|
||||
|
||||
while (alreadyHavePercent <= percent)
|
||||
{
|
||||
if (i >= iterated.size())
|
||||
{
|
||||
if (!stack.empty())
|
||||
{
|
||||
iterated = stack.top().first;
|
||||
i = stack.top().second;
|
||||
|
||||
stack.pop();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
SpfInterval* interval = iterated[i];
|
||||
if (!interval || interval->isRegion || interval->isNested)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
double time = performIntervalTime(project, interval, gCovInfo, calls);
|
||||
int count = countOfIntervals(interval, mainInterval);
|
||||
if (count != 0) time *= count;
|
||||
double percentOfInterval = time / sumTime;
|
||||
|
||||
if (percentOfInterval + alreadyHavePercent <= percent)
|
||||
{
|
||||
__spf_print(1, "Add interval with %f percent, we have %f percent\n", percentOfInterval, percentOfInterval + alreadyHavePercent);
|
||||
SpfRegion region(id, time, interval->begin, interval->ends[0]);
|
||||
region.time = time;
|
||||
region.id = id;
|
||||
iterated[i]->isRegion = true;
|
||||
markNestedIntervals(interval);
|
||||
id++;
|
||||
i++;
|
||||
|
||||
regions.push_back(region);
|
||||
alreadyHavePercent += percentOfInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_print(1, "divide interval with %f percent\n", percentOfInterval);
|
||||
if (i < iterated.size() - 1)
|
||||
stack.push(make_pair(vector<SpfInterval*>(iterated.begin(), iterated.end()), i + 1));
|
||||
|
||||
iterated.clear();
|
||||
iterated = vector<SpfInterval*>(interval->nested.begin(), interval->nested.end());
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < regions.size())
|
||||
{
|
||||
if (i > 0 && !regions[i-1].end->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (i > 0 && regions[i - 1].end->lexNext() == regions[i].start)
|
||||
{
|
||||
regions[i - 1].end = regions[i].end;
|
||||
regions.erase(regions.begin() + i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
__spf_print(1, "Coverage of region is %f percent, count of regions is %d\n", alreadyHavePercent, regions.size());
|
||||
|
||||
for (auto &item : regions)
|
||||
{
|
||||
if (!item.start->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgStatement *startRegion = new SgStatement(SPF_PARALLEL_REG_DIR);
|
||||
SgStatement *endRegion = new SgStatement(SPF_END_PARALLEL_REG_DIR);
|
||||
|
||||
startRegion->setSymbol(*(new SgSymbol(VARIABLE_NAME, to_string(item.id).c_str())));
|
||||
|
||||
SgStatement *st = item.start;
|
||||
while (!isSgExecutableStatement(st))
|
||||
st = st->lexNext();
|
||||
|
||||
startRegion->setFileId(st->getFileId());
|
||||
startRegion->setProject(st->getProject());
|
||||
startRegion->setlineNumber(st->lineNumber());
|
||||
startRegion->setFileName(st->fileName());
|
||||
|
||||
st->insertStmtBefore(*startRegion, *st->controlParent());
|
||||
|
||||
SgStatement *next = item.end->lexNext();
|
||||
startRegion->setFileId(next->getFileId());
|
||||
startRegion->setProject(next->getProject());
|
||||
startRegion->setlineNumber(next->lineNumber());
|
||||
startRegion->setFileName(next->fileName());
|
||||
|
||||
next->insertStmtBefore(*endRegion, *next->controlParent());
|
||||
}
|
||||
}
|
||||
34
Sapfor/_src/DynamicAnalysis/createParallelRegions.h
Normal file
34
Sapfor/_src/DynamicAnalysis/createParallelRegions.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
#include "./gcov_info.h"
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
struct SpfRegion
|
||||
{
|
||||
int id;
|
||||
|
||||
double time;
|
||||
SgStatement *start;
|
||||
SgStatement *end;
|
||||
|
||||
SpfRegion(int id_, int time_, SgStatement *start_, SgStatement *end_) :
|
||||
id(id_), time(time_), start(start_), end(end_) {}
|
||||
|
||||
SpfRegion& operator+=(const SpfRegion &rg)
|
||||
{
|
||||
if (this != &rg)
|
||||
{
|
||||
end = rg.end;
|
||||
time += rg.time;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
void createParallelRegions(SgProject *project, SpfInterval *mainInterval, const std::map<std::string, std::map<int, Gcov_info>> &gCovInfo, const std::map<std::string, std::vector<FuncInfo*>> &funcInfo);
|
||||
473
Sapfor/_src/DynamicAnalysis/gCov_parser.cpp
Normal file
473
Sapfor/_src/DynamicAnalysis/gCov_parser.cpp
Normal file
@@ -0,0 +1,473 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "gCov_parser_func.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum key_word
|
||||
{
|
||||
UNKNOWN,
|
||||
BRANCH,
|
||||
CALL,
|
||||
};
|
||||
|
||||
static const char *key_words[] =
|
||||
{
|
||||
"",
|
||||
"branch",
|
||||
"call",
|
||||
"taken",
|
||||
"returned",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *symbols_neverExecuted[] =
|
||||
{
|
||||
"",
|
||||
"#####",
|
||||
"%%%%%",
|
||||
"$$$$$",
|
||||
"=====",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void isKeyWord(const string &lex, key_word &lineType)
|
||||
{
|
||||
int i = 1;
|
||||
bool find = false;
|
||||
while ((!find) && key_words[i]) {
|
||||
if (lex.compare(key_words[i]) == 0)
|
||||
find = true;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
switch (i) {
|
||||
case 1:
|
||||
lineType = BRANCH;
|
||||
break;
|
||||
case 2:
|
||||
lineType = CALL;
|
||||
break;
|
||||
default:
|
||||
if (lineType != UNKNOWN)
|
||||
{
|
||||
__spf_print(1, "Error: Wrong work of analysis keywords\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isNeverExecuted(const string &lex)
|
||||
{
|
||||
int i = 1;
|
||||
bool find = false;
|
||||
while ((!find) && symbols_neverExecuted[i])
|
||||
{
|
||||
if (lex.compare(symbols_neverExecuted[i]) == 0)
|
||||
find = true;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return find;
|
||||
}
|
||||
|
||||
static void getInfo(map<int, Gcov_info> &info, const string &str)
|
||||
{
|
||||
Gcov_info infoLine;
|
||||
Perform infoPerform;
|
||||
string num, lex;
|
||||
key_word lineType = UNKNOWN;
|
||||
bool executedCountGot = false;
|
||||
int i = 0;
|
||||
int len = str.length();
|
||||
int minus = 0;
|
||||
int ddot = 0;
|
||||
while (i != len)
|
||||
{
|
||||
char c = str[i];
|
||||
if ((c >= 48) && (c <= 57)) //symbols '0'-'9'
|
||||
num.push_back(c);
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
if ((!lex.empty()) && (lineType == UNKNOWN))
|
||||
isKeyWord(lex, lineType);
|
||||
lex.clear();
|
||||
if ((!num.empty()) && ((lineType == BRANCH) || (lineType == CALL)))
|
||||
infoPerform.setNumber(stoi(num, nullptr));
|
||||
num.clear();
|
||||
break;
|
||||
case ':':
|
||||
ddot++;
|
||||
if ((!lex.empty()) && (isNeverExecuted(lex)))
|
||||
{
|
||||
executedCountGot = true;
|
||||
infoLine.setExecutedCount(0);
|
||||
}
|
||||
if (!num.empty())
|
||||
{
|
||||
if (!executedCountGot)
|
||||
{
|
||||
const int64_t value = stoll(num);
|
||||
if (minus == 1 && ddot == 1 && value == 0)
|
||||
infoLine.setExecutedCount(-1);
|
||||
else
|
||||
infoLine.setExecutedCount(value);
|
||||
executedCountGot = true;
|
||||
}
|
||||
else
|
||||
infoLine.setNumLine(stoi(num, nullptr));
|
||||
}
|
||||
num.clear();
|
||||
break;
|
||||
case '%':
|
||||
if (!num.empty())
|
||||
infoPerform.setPercent(stoi(num, nullptr));
|
||||
num.clear();
|
||||
break;
|
||||
case '-':
|
||||
minus++;
|
||||
num.push_back('0');
|
||||
break;
|
||||
default:
|
||||
//Try find 'branch' or 'call'
|
||||
lex.push_back(c);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (infoLine.getNumLine() != -1)
|
||||
info.insert(make_pair(infoLine.getNumLine(), infoLine));
|
||||
|
||||
switch (lineType)
|
||||
{
|
||||
case BRANCH:
|
||||
((*(info.rbegin())).second).setBranch(infoPerform);
|
||||
break;
|
||||
case CALL:
|
||||
((*(info.rbegin())).second).setCall(infoPerform);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
break;
|
||||
default:
|
||||
__spf_print(1, "Error: get unreal type\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void printPerform(map<int, Perform> info, ostream &myfile)
|
||||
{
|
||||
map<int, Perform>::iterator cur;
|
||||
for (cur = info.begin(); cur != info.end(); cur++)
|
||||
myfile << (*cur).first << ")" << (*cur).second;
|
||||
}
|
||||
|
||||
static void printInfo2file(map<int, Gcov_info> &info, ostream &myfile)
|
||||
{
|
||||
map<int, Gcov_info>::iterator cur;
|
||||
for (cur = info.begin(); cur != info.end(); cur++)
|
||||
{
|
||||
Gcov_info cur_gcov = (*cur).second;
|
||||
myfile << "_________________\n";
|
||||
myfile << "№" << (*cur).first << endl << cur_gcov;
|
||||
if (cur_gcov.getCountCalls() != 0)
|
||||
{
|
||||
myfile << "-----Calls----\n";
|
||||
printPerform(cur_gcov.getCalls(), myfile);
|
||||
}
|
||||
|
||||
if (cur_gcov.getCountBranches() != 0)
|
||||
{
|
||||
myfile << "----Branches----\n";
|
||||
printPerform(cur_gcov.getBranches(), myfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline string modify_name(const string &name)
|
||||
{
|
||||
return name + "_pgcov.txt";
|
||||
}
|
||||
|
||||
/*
|
||||
-добавить флаги при компиляции : gfortran -O2 -g -fprofile-arcs -ftest-coverage
|
||||
- запустить программу
|
||||
- отдать исходник профилировщику с флагом : LANG=en_US.utf8 gcov -b file.f
|
||||
*/
|
||||
|
||||
static void fixGcovInfo(SgFile *fileSg, map<int, Gcov_info> &gCovInfo)
|
||||
{
|
||||
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
|
||||
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
|
||||
{
|
||||
auto next = st->lexNext();
|
||||
const int currLine = st->lineNumber();
|
||||
const int nextLine = next ? next->lineNumber() : -1;
|
||||
if (next)
|
||||
{
|
||||
if (nextLine == currLine)
|
||||
continue;
|
||||
|
||||
auto it = gCovInfo.find(currLine);
|
||||
|
||||
if (it != gCovInfo.end())
|
||||
{
|
||||
if (it->second.getExecutedCount() <= 0)
|
||||
{
|
||||
int nextL = currLine + 1;
|
||||
while (nextL != nextLine)
|
||||
{
|
||||
auto itNext = gCovInfo.find(nextL);
|
||||
if (itNext != gCovInfo.end())
|
||||
{
|
||||
if (itNext->second.getExecutedCount() >= 0)
|
||||
{
|
||||
it->second.clear();
|
||||
it->second.setExecutedCount(itNext->second.getExecutedCount());
|
||||
for (auto &call : itNext->second.getCalls())
|
||||
it->second.setCall(call.second);
|
||||
for (auto &branch : itNext->second.getBranches())
|
||||
it->second.setBranch(branch.second);
|
||||
|
||||
// copy to between
|
||||
for (int z = currLine + 1; z != nextL; ++z)
|
||||
{
|
||||
auto itZ = gCovInfo.find(z);
|
||||
if (itZ != gCovInfo.end())
|
||||
{
|
||||
itZ->second.clear();
|
||||
itZ->second.setExecutedCount(itNext->second.getExecutedCount());
|
||||
for (auto &call : itNext->second.getCalls())
|
||||
itZ->second.setCall(call.second);
|
||||
for (auto &branch : itNext->second.getBranches())
|
||||
itZ->second.setBranch(branch.second);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextL++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
|
||||
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
|
||||
{
|
||||
if (st->variant() == CONTROL_END)
|
||||
{
|
||||
auto cp = st->controlParent();
|
||||
auto it = gCovInfo.find(cp->lineNumber());
|
||||
if (it != gCovInfo.end() && cp->variant() != PROG_HEDR &&
|
||||
cp->variant() != PROC_HEDR && cp->variant() != FUNC_HEDR &&
|
||||
isSgExecutableStatement(cp))
|
||||
{
|
||||
auto it = gCovInfo.find(st->lineNumber());
|
||||
auto itCp = gCovInfo.find(cp->lineNumber());
|
||||
if (it != gCovInfo.end())
|
||||
{
|
||||
it->second.clear();
|
||||
it->second.setExecutedCount(itCp->second.getExecutedCount());
|
||||
for (auto &call : itCp->second.getCalls())
|
||||
it->second.setCall(call.second);
|
||||
for (auto &branch : itCp->second.getBranches())
|
||||
it->second.setBranch(branch.second);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static map<string, map<int, Gcov_info>*> allGCovInfo;
|
||||
void parse_gcovfile(SgFile *fileSg, const string &basefileNameIn, map<int, Gcov_info> &gCovInfo, bool keep)
|
||||
{
|
||||
if (basefileNameIn == "")
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else
|
||||
{
|
||||
const string basefileName = basefileNameIn + ".gcov";
|
||||
ifstream file;
|
||||
file.open(basefileName, ios::in);
|
||||
if (file.is_open())
|
||||
{
|
||||
string str;
|
||||
while (!file.eof())
|
||||
{
|
||||
getline(file, str);
|
||||
getInfo(gCovInfo, str);
|
||||
}
|
||||
file.close();
|
||||
fixGcovInfo(fileSg, gCovInfo);
|
||||
|
||||
if (keep)
|
||||
{
|
||||
// FOR DEBUG ONLY
|
||||
string name_f = modify_name(basefileName);
|
||||
ofstream myfile(name_f);
|
||||
if (myfile.is_open())
|
||||
printInfo2file(gCovInfo, myfile);
|
||||
else
|
||||
__spf_print(1, " Error: unable to create file %s\n", name_f.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
__spf_print(1, " Error: unable to open file %s\n", basefileName.c_str());
|
||||
}
|
||||
allGCovInfo[fileSg->filename()] = &gCovInfo;
|
||||
}
|
||||
|
||||
bool __gcov_doesThisLineExecuted(const string &file, const int line)
|
||||
{
|
||||
bool ret = true;
|
||||
auto itF = allGCovInfo.find(file);
|
||||
if (itF != allGCovInfo.end())
|
||||
{
|
||||
auto itL = itF->second->find(line);
|
||||
if (itL != itF->second->end())
|
||||
ret = itL->second.getExecutedCount() != 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pair<int, int64_t> __gcov_GetExecuted(const string &file, const int line)
|
||||
{
|
||||
pair<int, int64_t> ret = make_pair(0, 0);
|
||||
auto itF = allGCovInfo.find(file);
|
||||
if (itF != allGCovInfo.end())
|
||||
{
|
||||
auto itL = itF->second->find(line);
|
||||
if (itL != itF->second->end())
|
||||
ret.second = itL->second.getExecutedCount();
|
||||
else
|
||||
ret.first = -1;
|
||||
}
|
||||
else
|
||||
ret.first = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void parseTimesDvmStatisticFile(const string &file, map<string, vector<SpfInterval*>> &intervals)
|
||||
{
|
||||
map<string, map<int, SpfInterval*>> mapOfIntervals;
|
||||
for (auto &intByfile : intervals)
|
||||
createMapOfinterval(mapOfIntervals[intByfile.first], intByfile.second);
|
||||
|
||||
FILE *stat = fopen(file.c_str(), "r");
|
||||
if (stat)
|
||||
{
|
||||
char buf[8192];
|
||||
int execDone = 1;
|
||||
int line = -1;
|
||||
string fileN = "";
|
||||
SpfInterval *curr = NULL;
|
||||
|
||||
while (!feof(stat))
|
||||
{
|
||||
char *read = fgets(buf, 8192, stat);
|
||||
if (read)
|
||||
{
|
||||
const string origLine(read);
|
||||
auto itF = origLine.find("INTERVAL");
|
||||
auto itTypeU = origLine.find("USER");
|
||||
auto itExpr = origLine.find("EXPR=");
|
||||
if (itF != string::npos && itTypeU != string::npos && itExpr != string::npos)
|
||||
{
|
||||
execDone = 0;
|
||||
line = -1;
|
||||
fileN = "";
|
||||
int expr = 0;
|
||||
curr = NULL;
|
||||
|
||||
auto itL = origLine.find("NLINE=");
|
||||
if (itL != string::npos)
|
||||
{
|
||||
string lineS = "";
|
||||
for (size_t z = itL + 6; origLine[z] != ' '; ++z)
|
||||
lineS += origLine[z];
|
||||
line = atoi(lineS.c_str());
|
||||
}
|
||||
|
||||
auto itS = origLine.find("SOURCE=");
|
||||
if (itS != string::npos)
|
||||
{
|
||||
string source = "";
|
||||
for (size_t z = itS + 7; origLine[z] != ' '; ++z)
|
||||
source += origLine[z];
|
||||
fileN = source;
|
||||
convertToLower(fileN);
|
||||
}
|
||||
|
||||
string exprS = "";
|
||||
for (size_t z = itExpr + 5; origLine[z] != '\n'; ++z)
|
||||
exprS += origLine[z];
|
||||
expr = atoi(exprS.c_str());
|
||||
|
||||
if (line != -1 && fileN != "")
|
||||
{
|
||||
auto itIntF = mapOfIntervals.find(fileN);
|
||||
if (itIntF == mapOfIntervals.end())
|
||||
{
|
||||
//TODO: error
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &inter : itIntF->second)
|
||||
{
|
||||
if (inter.second->tag == expr)
|
||||
{
|
||||
curr = inter.second;
|
||||
string execCountS = "";
|
||||
auto itExec = origLine.find("EXE_COUNT=");
|
||||
string execS = "";
|
||||
for (size_t z = itExec + 10; origLine[z] != ' '; ++z)
|
||||
execS += origLine[z];
|
||||
inter.second->exec_count = atoi(execS.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto itE = origLine.find("Execution time");
|
||||
if (itE != string::npos && execDone == 0)
|
||||
{
|
||||
execDone = 1;
|
||||
size_t idx = 16;
|
||||
while (origLine[idx++] == ' ');
|
||||
string execC = "";
|
||||
for (size_t z = idx - 1; z < origLine.size(); ++z)
|
||||
execC += origLine[z];
|
||||
double execTime = atof(execC.c_str());
|
||||
|
||||
if (line != -1 && fileN != "" && curr)
|
||||
curr->exec_time += execTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(stat);
|
||||
}
|
||||
else
|
||||
__spf_print(1, " Error: unable to open file %s\n", file.c_str());
|
||||
}
|
||||
15
Sapfor/_src/DynamicAnalysis/gCov_parser_func.h
Normal file
15
Sapfor/_src/DynamicAnalysis/gCov_parser_func.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "gcov_info.h"
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
|
||||
void parse_gcovfile(SgFile *file, const std::string &basefileName, std::map<int, Gcov_info> &gCovInfo, bool keep);
|
||||
bool __gcov_doesThisLineExecuted(const std::string &file, const int line);
|
||||
std::pair<int, int64_t> __gcov_GetExecuted(const std::string &file, const int line);
|
||||
void parseTimesDvmStatisticFile(const std::string &file, std::map<std::string, std::vector<SpfInterval*>> &intervals);
|
||||
48
Sapfor/_src/DynamicAnalysis/gcov_info.cpp
Normal file
48
Sapfor/_src/DynamicAnalysis/gcov_info.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
#include "gcov_info.h"
|
||||
|
||||
using std::map;
|
||||
using std::make_pair;
|
||||
using std::ostream;
|
||||
using std::endl;
|
||||
|
||||
Gcov_info::Gcov_info() { numLine = -1; executedCount = -1; countCalls = 0; countBranches = 0; }
|
||||
Gcov_info::Gcov_info(int a, int b) { numLine = a; executedCount = b; }
|
||||
|
||||
void Gcov_info::set(int a, int64_t b, int c, int d) { numLine = a; executedCount = b; countCalls = c; countBranches = d; }
|
||||
|
||||
int Gcov_info::getNumLine() const { return numLine; }
|
||||
int64_t Gcov_info::getExecutedCount() const { return executedCount; }
|
||||
void Gcov_info::setNumLine(int a) { numLine = a; }
|
||||
void Gcov_info::setExecutedCount(int64_t a) { executedCount = a; }
|
||||
void Gcov_info::setCall(Perform a) { countCalls++; calls.insert(make_pair(a.getNumber(), a)); }
|
||||
void Gcov_info::setBranch(Perform a) { countBranches++; branches.insert(make_pair(a.getNumber(), a)); }
|
||||
map<int, Perform> Gcov_info::getCalls() const { return calls; }
|
||||
map<int, Perform> Gcov_info::getBranches() const { return branches; }
|
||||
int Gcov_info::getCountCalls() const { return countCalls; }
|
||||
int Gcov_info::getCountBranches() const { return countBranches; }
|
||||
void Gcov_info::gcov_print() const { __spf_print(1, "%d - %lld\n", numLine, executedCount); }
|
||||
ostream &operator<<(ostream &out, const Gcov_info &a) {
|
||||
out << "numLine= " << a.numLine << "\nexecutedCount= " << a.executedCount <<
|
||||
"\ncountCalls= " << a.countCalls << "\ncountBranches= " << a.countBranches << endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
//-------------------------Perform-----------------------------------------
|
||||
|
||||
Perform::Perform() { number = -1; percent = -1; }
|
||||
Perform::Perform(int a, int b) { number = a; percent = b; }
|
||||
void Perform::set(int a, int b) { number = a; percent = b; }
|
||||
int Perform::getNumber() { return number; }
|
||||
int Perform::getPercent() { return percent; }
|
||||
void Perform::setNumber(int a) { number = a; }
|
||||
void Perform::setPercent(int a) { percent = a; }
|
||||
void Perform::gcov_print() { __spf_print(1, "%d - %d\n", number, percent); }
|
||||
ostream &operator<<(ostream &out, const Perform &a) { out << "number= " << a.number << ": percent= " << a.percent << endl; return out; }
|
||||
53
Sapfor/_src/DynamicAnalysis/gcov_info.h
Normal file
53
Sapfor/_src/DynamicAnalysis/gcov_info.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
//make 'class' - need friend for Gcov_info
|
||||
struct Perform
|
||||
{
|
||||
int number;
|
||||
int percent;
|
||||
|
||||
Perform();
|
||||
Perform(int a, int b);
|
||||
void set(int a, int b);
|
||||
int getNumber();
|
||||
int getPercent();
|
||||
void setNumber(int a);
|
||||
void setPercent(int a);
|
||||
void gcov_print();
|
||||
friend std::ostream &operator<<(std::ostream &out, const Perform &a);
|
||||
};
|
||||
|
||||
class Gcov_info
|
||||
{
|
||||
int numLine;
|
||||
int64_t executedCount;
|
||||
int countCalls;
|
||||
std::map<int, Perform> calls;
|
||||
int countBranches;
|
||||
std::map<int, Perform> branches;
|
||||
|
||||
public:
|
||||
Gcov_info();
|
||||
Gcov_info(int a, int b);
|
||||
void set(int a, int64_t b, int c, int d);
|
||||
void clear() { calls.clear(); branches.clear(); countCalls = 0; countBranches = 0; }
|
||||
int getNumLine() const;
|
||||
int64_t getExecutedCount() const;
|
||||
void setNumLine(int a);
|
||||
void setExecutedCount(int64_t a);
|
||||
int getCountCalls() const;
|
||||
int getCountBranches() const;
|
||||
std::map<int,Perform> getCalls() const;
|
||||
std::map<int,Perform> getBranches() const;
|
||||
void setCall(Perform a);
|
||||
void setBranch(Perform a);
|
||||
void gcov_print() const;
|
||||
friend std::ostream &operator<<(std::ostream &out, const Gcov_info &a);
|
||||
};
|
||||
Reference in New Issue
Block a user