Extend interprocedural analysis

This commit is contained in:
2025-05-01 11:43:35 +03:00
parent 400b1e8e92
commit f8de920442
2 changed files with 249 additions and 126 deletions

View File

@@ -27,6 +27,7 @@ using namespace std;
tuple<FuncInfo*, SAPFOR::Instruction*, SAPFOR::BasicBlock*> stmtToIR(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph, SgStatement* stmt) tuple<FuncInfo*, SAPFOR::Instruction*, SAPFOR::BasicBlock*> stmtToIR(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph, SgStatement* stmt)
{ {
SgStatement* cur = stmt; SgStatement* cur = stmt;
cur->switchToFile();
while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR) while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR)
cur = cur->controlParent(); cur = cur->controlParent();
@@ -48,8 +49,22 @@ tuple<FuncInfo*, SAPFOR::Instruction*, SAPFOR::BasicBlock*> stmtToIR(const map<F
return { NULL, NULL, NULL }; return { NULL, NULL, NULL };
} }
tuple<FuncInfo*, SAPFOR::Instruction*, SAPFOR::BasicBlock*> IRByNumber(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph, int num)
{
if (num < 0)
return { NULL, NULL, NULL };
for (const auto& [func, bblocks] : CFGraph)
for (auto byBB : bblocks)
if (byBB->getInstructions().front()->getNumber() <= num && byBB->getInstructions().back()->getNumber() >= num)
return make_tuple(func, getInstructionByNumber(byBB->getInstructions(), num), byBB);
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return { NULL, NULL, NULL};
}
template<typename Iterator> template<typename Iterator>
static void processArgument(set<SAPFOR::Argument*>& worklist, void processArgument(set<SAPFOR::Argument*>& worklist,
SAPFOR::Argument* arg, SAPFOR::Argument* arg,
Iterator instr, Iterator instr,
Iterator first_instr) Iterator first_instr)
@@ -58,7 +73,7 @@ static void processArgument(set<SAPFOR::Argument*>& worklist,
return; return;
if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG)
extract_vars_from_reg(worklist, arg, instr, first_instr); extract_vars_from_reg(worklist, arg, instr, first_instr);
else if (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::LOCAL_) else if (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{ {
std::cout << "worklist add: " << arg->getValue() << std::endl; //DEBUG PRINT std::cout << "worklist add: " << arg->getValue() << std::endl; //DEBUG PRINT
worklist.insert(arg); worklist.insert(arg);
@@ -66,7 +81,7 @@ static void processArgument(set<SAPFOR::Argument*>& worklist,
} }
template<typename Iterator> template<typename Iterator>
static void extract_vars_from_reg(set<SAPFOR::Argument*>& worklist, void extract_vars_from_reg(set<SAPFOR::Argument*>& worklist,
SAPFOR::Argument* reg, SAPFOR::Argument* reg,
Iterator instr, Iterator instr,
Iterator first_instr) Iterator first_instr)
@@ -82,12 +97,15 @@ static void extract_vars_from_reg(set<SAPFOR::Argument*>& worklist,
} }
} }
static void lookup_for_vars(std::map<SgStatement*, std::string>& where_to_add, void lookup_for_vars(std::set<std::tuple<SgStatement*, std::string, MODE>>& where_to_add,
set<SAPFOR::Argument*>& worklist, set<SAPFOR::Argument*>& worklist,
SAPFOR::Instruction* instr, SAPFOR::Instruction* instr,
SAPFOR::BasicBlock* bblock, SAPFOR::BasicBlock* bblock,
FuncInfo* cur_func,
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR) const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR)
{ {
while (bblock)
{
std::cout << "Lookup in bblock no." << bblock->getNumber() << std::endl; //DEBUG PRINT std::cout << "Lookup in bblock no." << bblock->getNumber() << std::endl; //DEBUG PRINT
auto first_instr = bblock->getInstructions().begin(); auto first_instr = bblock->getInstructions().begin();
@@ -98,6 +116,7 @@ static void lookup_for_vars(std::map<SgStatement*, std::string>& where_to_add,
for (; cur_instr >= bblock->getInstructions().begin(); cur_instr--) for (; cur_instr >= bblock->getInstructions().begin(); cur_instr--)
{ {
auto instr = (*cur_instr)->getInstruction(); auto instr = (*cur_instr)->getInstruction();
// std::cout << instr->getNumber() << '\n';
auto result_arg = instr->getResult(); auto result_arg = instr->getResult();
auto arg1 = instr->getArg1(); auto arg1 = instr->getArg1();
auto arg2 = instr->getArg2(); auto arg2 = instr->getArg2();
@@ -122,13 +141,11 @@ static void lookup_for_vars(std::map<SgStatement*, std::string>& where_to_add,
auto filename = stmt_before->fileName(); auto filename = stmt_before->fileName();
auto line = stmt_before->lineNumber(); auto line = stmt_before->lineNumber();
auto var_name = arg1->getValue().substr(arg1->getValue().find('%') + 1); auto var_name = arg1->getValue().substr(arg1->getValue().find('%') + 1);
__spf_print(1,"Please specify value of variable %s on line %d of file %s", arg1->getValue().c_str(), line, filename); __spf_print(1,"Please specify value of variable %s on line %d of file %s\n", arg1->getValue().c_str(), line, filename);
where_to_add[stmt_before] = var_name; auto toAdd = make_tuple(stmt_before, var_name, MODE::AFTER);
where_to_add.insert(toAdd);
std::cout << "worklist erase: " << arg1->getValue() << std::endl; //DEBUG PRINT std::cout << "worklist erase: " << arg1->getValue() << std::endl; //DEBUG PRINT
worklist.erase(arg1); worklist.erase(arg1);
} else
{
//check if variable is modified in called function
} }
} }
} }
@@ -142,32 +159,116 @@ static void lookup_for_vars(std::map<SgStatement*, std::string>& where_to_add,
if (RD.at(arg).size() == 1 && *RD.at(arg).begin() == SAPFOR::CFG_VAL::UNINIT) if (RD.at(arg).size() == 1 && *RD.at(arg).begin() == SAPFOR::CFG_VAL::UNINIT)
__spf_print(1, "variable %s has no definition", arg->getValue().c_str()); __spf_print(1, "variable %s has no definition", arg->getValue().c_str());
else if (RD.at(arg).size() > 1) else if (RD.at(arg).size() > 1)
__spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible", arg->getValue().c_str()); {
auto stmt_after = (*first_instr)->getInstruction()->getOperator();
auto filename = stmt_after->fileName();
auto line = stmt_after->lineNumber();
auto var_name = arg->getValue().substr(arg->getValue().find('%') + 1);
__spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible\n", arg->getValue().c_str());
__spf_print(1,"Please specify value of variable %s on line %d of file %s\n", arg->getValue().c_str(), line, filename);
auto toAdd = make_tuple(stmt_after, var_name, MODE::BEFORE);
where_to_add.insert(toAdd);
std::cout << "worklist erase: " << arg->getValue() << std::endl; //DEBUG PRINT
worklist.erase(arg);
}
else else
{ {
for (const auto& instr_num : RD.at(arg)) auto instr_num = *RD.at(arg).begin();
{ auto [func, instr, bblock] = IRByNumber(fullIR, instr_num);
auto [instr, bblock] = getInstructionAndBlockByNumber(fullIR, instr_num); if (cur_func == func && group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num)
if (group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num)
group_by_block[bblock] = instr; group_by_block[bblock] = instr;
} }
} }
} }
while (bblock && group_by_block.find(bblock) == group_by_block.end())
bblock = bblock->getIdom();
if (bblock)
instr = group_by_block[bblock];
} }
auto idom = bblock->getIdom(); // other variables are from global scope
while (idom != NULL) const auto& RD = fullIR.at(cur_func).front()->getRD_In();
for (auto& arg : worklist)
{ {
if (group_by_block.count(idom)) if (arg->isMemGlobal())
{ {
lookup_for_vars(where_to_add, worklist, group_by_block[idom], idom, fullIR); std::cout << "global: " << arg->getValue() << " : " << RD.count(arg) << '\n';
return; set<int> found_rd;
if (RD.count(arg))
found_rd = RD.at(arg);
if (found_rd.size() == 0)
{
auto call_instr = call_sites[cur_func].size() ? call_sites[cur_func].front() : NULL;
while (call_instr && found_rd.size() == 0)
{
auto [call_func, _, call_bblock] = IRByNumber(fullIR, call_instr->getNumber());
std::cout << "caller: " << call_func->funcName << '\n';
if (call_bblock->getRD_Out().count(arg))
{
std::cout << *call_bblock->getRD_Out().at(arg).begin() << "\n";
found_rd = call_bblock->getRD_Out().at(arg);
} }
idom = idom->getIdom();
call_instr = call_sites[call_func].size() ? call_sites[call_func].front() : NULL;
} }
}
if (found_rd.size() == 1 && *found_rd.begin() == SAPFOR::CFG_VAL::UNINIT)
{
__spf_print(1, "variable %s has no definition", arg->getValue().c_str());
} else if (found_rd.size() > 1)
{
auto first_instr = fullIR.at(cur_func).front()->getInstructions().begin();
auto stmt_after = (*first_instr)->getInstruction()->getOperator();
auto filename = stmt_after->fileName();
auto line = stmt_after->lineNumber();
auto var_name = arg->getValue().substr(arg->getValue().find('%') + 1);
__spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible\n", arg->getValue().c_str());
__spf_print(1,"Please specify value of variable %s on line %d of file %s\n", arg->getValue().c_str(), line, filename);
auto toAdd = make_tuple(stmt_after, var_name, MODE::BEFORE);
where_to_add.insert(toAdd);
}
else
{
auto instr_num = *found_rd.begin();
auto [func, instr, bblock] = IRByNumber(fullIR, instr_num);
set<SAPFOR::Argument*> new_worklist = {arg};
lookup_for_vars(where_to_add, new_worklist, instr, bblock, func, fullIR);
}
}
}
for (const auto& call_instr : call_sites[cur_func])
{
set<SAPFOR::Argument*> new_worklist;
auto params_num = cur_func->funcParams.countOfPars;
auto [call_func, _, call_bblock] = IRByNumber(fullIR, call_instr->getNumber());
std::cout << "caller: " << call_func->funcName << '\n';
auto first_instr = call_bblock->getInstructions().begin();
auto cur_instr = std::find_if(first_instr, call_bblock->getInstructions().end(), [call_instr](SAPFOR::IR_Block* i) {
return i->getInstruction() == call_instr;
});
for (auto& arg : worklist)
{
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
{
auto param_num= stoi(arg->getValue().substr(arg->getValue().find('%', arg->getValue().find('%') + 1) + 1));
// std::cout << params_num << '\n';
auto param_instr = (cur_instr - (params_num - param_num));
auto param_arg = (*param_instr)->getInstruction()->getArg1();
std::cout << "param_val: " << param_arg->getValue() << " : " << param_num << '\n';
processArgument(new_worklist, param_arg, param_instr, first_instr);
}
}
lookup_for_vars(where_to_add, new_worklist, call_instr, call_bblock, call_func, fullIR);
}
} }
static void handle_single_allocate(std::map<SgStatement*, std::string>& where_to_add, void handle_single_allocate(std::set<tuple<SgStatement*, std::string, MODE>>& where_to_add,
SgStatement* alloc_statement, SgStatement* alloc_statement,
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR) const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR)
{ {
@@ -182,9 +283,8 @@ static void handle_single_allocate(std::map<SgStatement*, std::string>& where_to
// skip to F_CALL _ALLOC n // skip to F_CALL _ALLOC n
while ((*alloc_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL || while ((*alloc_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL ||
(*alloc_instr)->getInstruction()->getArg1()->getValue() != "_ALLOC") (*alloc_instr)->getInstruction()->getArg1()->getValue() != "_ALLOC")
{
alloc_instr++; alloc_instr++;
}
auto arrays_num = stoi((*alloc_instr)->getInstruction()->getArg2()->getValue()); auto arrays_num = stoi((*alloc_instr)->getInstruction()->getArg2()->getValue());
std::cout << "arrays_num: " << arrays_num << std::endl; //DEBUG PRINT std::cout << "arrays_num: " << arrays_num << std::endl; //DEBUG PRINT
@@ -197,36 +297,41 @@ static void handle_single_allocate(std::map<SgStatement*, std::string>& where_to
while ((*param_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::LOAD || while ((*param_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::LOAD ||
(*param_instr)->getInstruction()->getResult() != param_reg) (*param_instr)->getInstruction()->getResult() != param_reg)
{
param_instr--; param_instr--;
}
auto dimensions_num = stoi((*param_instr)->getInstruction()->getArg2()->getValue()); auto dimensions_num = stoi((*param_instr)->getInstruction()->getArg2()->getValue());
for (int j = 0; j < dimensions_num; j++) for (int j = 0; j < dimensions_num; j++)
{ {
auto ref_instr = --param_instr; auto ref_instr = --param_instr;
if ((*ref_instr)->getInstruction()->getOperation() == SAPFOR::CFG_OP::RANGE)
{
vector<SAPFOR::Argument*> range_args = {(*ref_instr)->getInstruction()->getArg1(),
(*ref_instr)->getInstruction()->getArg2(),
(*ref_instr)->getInstruction()->getResult()};
for (auto& arg : range_args)
{
if (arg)
std::cout << "range-arg: " << arg->getValue() << '\n';
processArgument(worklist, arg, ref_instr, first_instr);
}
} else
{
auto arg = (*ref_instr)->getInstruction()->getArg1(); auto arg = (*ref_instr)->getInstruction()->getArg1();
if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) processArgument(worklist, arg, ref_instr, first_instr);
{
extract_vars_from_reg(worklist, arg, ref_instr, first_instr);
}
else if (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::LOCAL_)
{
std::cout << "worklist add: " << arg->getValue() << std::endl; //DEBUG PRINT
worklist.insert(arg);
} }
} }
} }
lookup_for_vars(where_to_add,worklist, instr, bblock, fullIR); lookup_for_vars(where_to_add,worklist, instr, bblock, func, fullIR);
} }
static void handle_single_loop(std::map<SgStatement*, std::string>& where_to_add,
void handle_single_loop(std::set<tuple<SgStatement*, std::string, MODE>>& where_to_add,
SgStatement* loop_stmt, SgStatement* loop_stmt,
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR) const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR)
{ {
auto [func_name, instr, bblock] = stmtToIR(fullIR, loop_stmt); auto [func, instr, bblock] = stmtToIR(fullIR, loop_stmt);
std::cout << "bblock: " << bblock->getNumber() << " instr: " << instr->getNumber() << std::endl; std::cout << "bblock: " << bblock->getNumber() << " instr: " << instr->getNumber() << std::endl;
auto cur_instr = bblock->getInstructions().end() - 1; auto cur_instr = bblock->getInstructions().end() - 1;
@@ -234,7 +339,7 @@ static void handle_single_loop(std::map<SgStatement*, std::string>& where_to_add
set<SAPFOR::Argument*> worklist; set<SAPFOR::Argument*> worklist;
extract_vars_from_reg(worklist, (*cur_instr)->getInstruction()->getResult(), cur_instr, bblock->getInstructions().begin()); extract_vars_from_reg(worklist, (*cur_instr)->getInstruction()->getResult(), cur_instr, bblock->getInstructions().begin());
lookup_for_vars(where_to_add, worklist, (*cur_instr)->getInstruction(), bblock, fullIR); lookup_for_vars(where_to_add, worklist, (*cur_instr)->getInstruction(), bblock, func, fullIR);
} }
void void
@@ -242,13 +347,12 @@ findParameters(ResultSet& foundParameters,
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays) const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays)
{ {
map<SgStatement*, string> where_to_add; set<tuple<SgStatement*, string, MODE>> where_to_add;
map<string, FuncInfo*> name_to_func; map<string, FuncInfo*> name_to_func;
for (const auto& [func, _] : fullIR) for (const auto& [func, _] : fullIR)
name_to_func[func->funcName] = func; name_to_func[func->funcName] = func;
map<FuncInfo*, vector<SAPFOR::Instruction*>> call_sites;
for (auto& [func, bblocks] : fullIR) for (auto& [func, bblocks] : fullIR)
{ {
for (const auto& block : bblocks) for (const auto& block : bblocks)
@@ -277,18 +381,19 @@ findParameters(ResultSet& foundParameters,
} }
std::set<SgStatement*> alloc_statements; std::set<SgStatement*> alloc_statements;
for (const auto& elem : declaredArrays) for (const auto& [func, bblocks] : fullIR)
for (const auto& block : bblocks)
for (auto instr = block->getInstructions().begin(); instr != block->getInstructions().end(); ++instr)
{ {
const auto& array = elem.second.first; auto op = (*instr)->getInstruction()->getOperator();
SgSymbol* arraySymb = array->GetDeclSymbol()->GetOriginal(); if (op && op->variant() == ALLOCATE_STMT) {
SgStatement* decl = declaratedInStmt(arraySymb); alloc_statements.insert(op);
}
for (auto& stmt : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT }))
alloc_statements.insert(stmt);
} }
for (const auto& alloc_statement : alloc_statements) for (const auto& alloc_statement : alloc_statements)
{ {
alloc_statement->unparsestdout();
handle_single_allocate(where_to_add, alloc_statement, fullIR); handle_single_allocate(where_to_add, alloc_statement, fullIR);
} }
@@ -299,26 +404,34 @@ findParameters(ResultSet& foundParameters,
for (auto instr = block->getInstructions().begin(); instr != block->getInstructions().end(); ++instr) for (auto instr = block->getInstructions().begin(); instr != block->getInstructions().end(); ++instr)
{ {
auto op = (*instr)->getInstruction()->getOperator(); auto op = (*instr)->getInstruction()->getOperator();
if (op && op->variant() == FOR_NODE) { if (op && op->variant() == FOR_NODE)
std::cout << block->getNumber() << std::endl;
for_statements.insert(op); for_statements.insert(op);
} }
}
for (const auto& stmt : for_statements) for (const auto& stmt : for_statements)
{ {
std::cout << string(stmt->fileName()) << ":" << stmt->lineNumber() << '\n';
handle_single_loop(where_to_add, stmt, fullIR); handle_single_loop(where_to_add, stmt, fullIR);
} }
for (const auto& [stmt_before, var_name] : where_to_add) for (const auto& [stmt_before, var_name, mode] : where_to_add)
{ {
// SgVariableSymb* var_symb = new SgVariableSymb(var_name.c_str()); stmt_before->switchToFile();
// SgVarRefExp* var = new SgVarRefExp(var_symb); SgVariableSymb* var_symb = new SgVariableSymb(var_name.c_str());
// SgValueExp* zero = new SgValueExp(0); SgVarRefExp* var = new SgVarRefExp(var_symb);
// SgExprListExp* ex = new SgExprListExp(); SgValueExp* zero = new SgValueExp(1337);
// ex->setLhs(new SgExpression(ASSGN_OP, var, zero)); SgExprListExp* ex = new SgExprListExp();
// SgStatement* toAdd = new SgStatement(SPF_PARAMETER_OP, NULL, NULL, ex, NULL, NULL); ex->setLhs(new SgExpression(ASSGN_OP, var, zero));
// stmt_before->insertStmtAfter(*toAdd, *stmt_before->controlParent()); std::cout << "stmt_before: " << stmt_before->unparse();
SgStatement* toAdd = new SgStatement(ASSIGN_STAT, NULL, NULL, var, zero, NULL);
toAdd->unparsestdout();
// toAdd->lineNumber() = stmt_before->lineNumber();
toAdd->setlineNumber(stmt_before->lineNumber());
toAdd->setLocalLineNumber(stmt_before->lineNumber());
toAdd->setFileId(stmt_before->getFileId());
toAdd->setProject(stmt_before->getProject());
stmt_before->insertStmtAfter(*toAdd, *stmt_before->controlParent());
stmt_before->controlParent()->unparsestdout();
foundParameters.insert(make_tuple(stmt_before->fileName(), stmt_before->lineNumber(), var_name)); foundParameters.insert(make_tuple(stmt_before->fileName(), stmt_before->lineNumber(), var_name));
} }

View File

@@ -4,26 +4,36 @@
#include <map> #include <map>
#include <string> #include <string>
#include <set> #include <set>
#include <vector>
using ResultSet = std::set<std::tuple<std::string, int, std::string>>; using ResultSet = std::set<std::tuple<std::string, int, std::string>>;
enum class MODE
{
BEFORE,
AFTER
};
static std::map<FuncInfo*, std::vector<SAPFOR::Instruction*>> call_sites;
template<typename Iterator> template<typename Iterator>
static void extract_vars_from_reg(std::set<SAPFOR::Argument*>& worklist, void extract_vars_from_reg(std::set<SAPFOR::Argument*>& worklist,
SAPFOR::Argument* reg, SAPFOR::Argument* reg,
Iterator instr, Iterator instr,
Iterator first_instr); Iterator first_instr);
template<typename Iterator> template<typename Iterator>
static void processArgument(std::set<SAPFOR::Argument*>& worklist, void processArgument(std::set<SAPFOR::Argument*>& worklist,
SAPFOR::Argument* arg, SAPFOR::Argument* arg,
Iterator instr, Iterator instr,
Iterator first_instr); Iterator first_instr);
static void lookup_for_vars(std::map<SgStatement*, std::string>& where_to_add, void lookup_for_vars(std::set<std::tuple<SgStatement*, std::string, MODE>>& where_to_add,
std::set<SAPFOR::Argument*>& worklist, std::set<SAPFOR::Argument*>& worklist,
SAPFOR::Instruction* instr, SAPFOR::Instruction* instr,
SAPFOR::BasicBlock* bblock, SAPFOR::BasicBlock* bblock,
FuncInfo* cur_func,
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR); const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR);
void void