diff --git a/src/ProjectParameters/projectParameters.cpp b/src/ProjectParameters/projectParameters.cpp index 4a5f5c6..9919a51 100644 --- a/src/ProjectParameters/projectParameters.cpp +++ b/src/ProjectParameters/projectParameters.cpp @@ -27,6 +27,7 @@ using namespace std; tuple stmtToIR(const map>& CFGraph, SgStatement* stmt) { SgStatement* cur = stmt; + cur->switchToFile(); while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR) cur = cur->controlParent(); @@ -48,17 +49,31 @@ tuple stmtToIR(const map IRByNumber(const map>& 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 -static void processArgument(set& worklist, - SAPFOR::Argument* arg, - Iterator instr, - Iterator first_instr) +void processArgument(set& worklist, + SAPFOR::Argument* arg, + Iterator instr, + Iterator first_instr) { if (arg == NULL) return; if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) 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 worklist.insert(arg); @@ -66,10 +81,10 @@ static void processArgument(set& worklist, } template -static void extract_vars_from_reg(set& worklist, - SAPFOR::Argument* reg, - Iterator instr, - Iterator first_instr) +void extract_vars_from_reg(set& worklist, + SAPFOR::Argument* reg, + Iterator instr, + Iterator first_instr) { for (; instr >= first_instr; instr--) { @@ -82,94 +97,180 @@ static void extract_vars_from_reg(set& worklist, } } -static void lookup_for_vars(std::map& where_to_add, - set& worklist, - SAPFOR::Instruction* instr, - SAPFOR::BasicBlock* bblock, - const std::map>& fullIR) +void lookup_for_vars(std::set>& where_to_add, + set& worklist, + SAPFOR::Instruction* instr, + SAPFOR::BasicBlock* bblock, + FuncInfo* cur_func, + const std::map>& fullIR) { - std::cout << "Lookup in bblock no." << bblock->getNumber() << std::endl; //DEBUG PRINT - - auto first_instr = bblock->getInstructions().begin(); - auto cur_instr = std::find_if(first_instr, bblock->getInstructions().end(), [instr](SAPFOR::IR_Block* i) { - return i->getInstruction() == instr; - }); - - for (; cur_instr >= bblock->getInstructions().begin(); cur_instr--) + while (bblock) { - auto instr = (*cur_instr)->getInstruction(); - auto result_arg = instr->getResult(); - auto arg1 = instr->getArg1(); - auto arg2 = instr->getArg2(); + std::cout << "Lookup in bblock no." << bblock->getNumber() << std::endl; //DEBUG PRINT - if (worklist.count(result_arg)) - { - processArgument(worklist, arg1, cur_instr, first_instr); - processArgument(worklist, arg2, cur_instr, first_instr); - std::cout << "worklist erase: " << result_arg->getValue() << std::endl; //DEBUG PRINT - worklist.erase(result_arg); - } - if (instr->getOperation() == SAPFOR::CFG_OP::PARAM && worklist.count(arg1)) - { - // skip to F_CALL - auto f_call_instr = cur_instr; - while ((*f_call_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL) - f_call_instr++; + auto first_instr = bblock->getInstructions().begin(); + auto cur_instr = std::find_if(first_instr, bblock->getInstructions().end(), [instr](SAPFOR::IR_Block* i) { + return i->getInstruction() == instr; + }); - if ((*f_call_instr)->getInstruction()->getArg1()->getValue() == "_READ") + for (; cur_instr >= bblock->getInstructions().begin(); cur_instr--) + { + auto instr = (*cur_instr)->getInstruction(); + // std::cout << instr->getNumber() << '\n'; + auto result_arg = instr->getResult(); + auto arg1 = instr->getArg1(); + auto arg2 = instr->getArg2(); + + if (worklist.count(result_arg)) { - auto stmt_before = (*f_call_instr)->getInstruction()->getOperator(); - auto filename = stmt_before->fileName(); - auto line = stmt_before->lineNumber(); - 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); - where_to_add[stmt_before] = var_name; - std::cout << "worklist erase: " << arg1->getValue() << std::endl; //DEBUG PRINT - worklist.erase(arg1); - } else + processArgument(worklist, arg1, cur_instr, first_instr); + processArgument(worklist, arg2, cur_instr, first_instr); + std::cout << "worklist erase: " << result_arg->getValue() << std::endl; //DEBUG PRINT + worklist.erase(result_arg); + } + if (instr->getOperation() == SAPFOR::CFG_OP::PARAM && worklist.count(arg1)) { - //check if variable is modified in called function + // skip to F_CALL + auto f_call_instr = cur_instr; + while ((*f_call_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL) + f_call_instr++; + + if ((*f_call_instr)->getInstruction()->getArg1()->getValue() == "_READ") + { + auto stmt_before = (*f_call_instr)->getInstruction()->getOperator(); + auto filename = stmt_before->fileName(); + auto line = stmt_before->lineNumber(); + 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\n", arg1->getValue().c_str(), line, filename); + 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 + worklist.erase(arg1); + } } } - } - const auto& RD = bblock->getRD_In(); - map group_by_block; - for (auto& arg : worklist) - { - if (RD.count(arg)) + const auto& RD = bblock->getRD_In(); + map group_by_block; + for (auto& arg : worklist) { - 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()); - else if (RD.at(arg).size() > 1) - __spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible", arg->getValue().c_str()); - else + if (RD.count(arg)) { - for (const auto& instr_num : RD.at(arg)) + 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()); + else if (RD.at(arg).size() > 1) { - auto [instr, bblock] = getInstructionAndBlockByNumber(fullIR, instr_num); - if (group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num) + 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 + { + auto instr_num = *RD.at(arg).begin(); + auto [func, instr, bblock] = IRByNumber(fullIR, instr_num); + if (cur_func == func && group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num) 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(); - while (idom != NULL) + // other variables are from global scope + 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); - return; + std::cout << "global: " << arg->getValue() << " : " << RD.count(arg) << '\n'; + set 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); + } + + 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 new_worklist = {arg}; + + lookup_for_vars(where_to_add, new_worklist, instr, bblock, func, fullIR); + } } - idom = idom->getIdom(); } + + + for (const auto& call_instr : call_sites[cur_func]) + { + set 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& where_to_add, - SgStatement* alloc_statement, - const std::map>& fullIR) +void handle_single_allocate(std::set>& where_to_add, + SgStatement* alloc_statement, + const std::map>& fullIR) { auto [func, instr, bblock] = stmtToIR(fullIR, alloc_statement); @@ -182,9 +283,8 @@ static void handle_single_allocate(std::map& where_to // skip to F_CALL _ALLOC n while ((*alloc_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL || (*alloc_instr)->getInstruction()->getArg1()->getValue() != "_ALLOC") - { alloc_instr++; - } + auto arrays_num = stoi((*alloc_instr)->getInstruction()->getArg2()->getValue()); std::cout << "arrays_num: " << arrays_num << std::endl; //DEBUG PRINT @@ -197,36 +297,41 @@ static void handle_single_allocate(std::map& where_to while ((*param_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::LOAD || (*param_instr)->getInstruction()->getResult() != param_reg) - { param_instr--; - } + auto dimensions_num = stoi((*param_instr)->getInstruction()->getArg2()->getValue()); for (int j = 0; j < dimensions_num; j++) { auto ref_instr = --param_instr; - - auto arg = (*ref_instr)->getInstruction()->getArg1(); - if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) + if ((*ref_instr)->getInstruction()->getOperation() == SAPFOR::CFG_OP::RANGE) { - 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_) + vector 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 { - std::cout << "worklist add: " << arg->getValue() << std::endl; //DEBUG PRINT - worklist.insert(arg); + auto arg = (*ref_instr)->getInstruction()->getArg1(); + processArgument(worklist, arg, ref_instr, first_instr); } } } - 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& where_to_add, - SgStatement* loop_stmt, - const std::map>& fullIR) + +void handle_single_loop(std::set>& where_to_add, + SgStatement* loop_stmt, + const std::map>& 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; auto cur_instr = bblock->getInstructions().end() - 1; @@ -234,7 +339,7 @@ static void handle_single_loop(std::map& where_to_add set worklist; 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 @@ -242,13 +347,12 @@ findParameters(ResultSet& foundParameters, std::map>& fullIR, const std::map, std::pair>& declaredArrays) { - map where_to_add; + set> where_to_add; map name_to_func; for (const auto& [func, _] : fullIR) name_to_func[func->funcName] = func; - map> call_sites; for (auto& [func, bblocks] : fullIR) { for (const auto& block : bblocks) @@ -277,18 +381,19 @@ findParameters(ResultSet& foundParameters, } std::set alloc_statements; - for (const auto& elem : declaredArrays) - { - const auto& array = elem.second.first; - SgSymbol* arraySymb = array->GetDeclSymbol()->GetOriginal(); - SgStatement* decl = declaratedInStmt(arraySymb); - - for (auto& stmt : getAttributes(decl, set{ ALLOCATE_STMT })) - alloc_statements.insert(stmt); - } + for (const auto& [func, bblocks] : fullIR) + for (const auto& block : bblocks) + for (auto instr = block->getInstructions().begin(); instr != block->getInstructions().end(); ++instr) + { + auto op = (*instr)->getInstruction()->getOperator(); + if (op && op->variant() == ALLOCATE_STMT) { + alloc_statements.insert(op); + } + } for (const auto& alloc_statement : alloc_statements) { + alloc_statement->unparsestdout(); 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) { auto op = (*instr)->getInstruction()->getOperator(); - if (op && op->variant() == FOR_NODE) { - std::cout << block->getNumber() << std::endl; + if (op && op->variant() == FOR_NODE) for_statements.insert(op); - } } for (const auto& stmt : for_statements) { + std::cout << string(stmt->fileName()) << ":" << stmt->lineNumber() << '\n'; 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()); - // SgVarRefExp* var = new SgVarRefExp(var_symb); - // SgValueExp* zero = new SgValueExp(0); - // SgExprListExp* ex = new SgExprListExp(); - // ex->setLhs(new SgExpression(ASSGN_OP, var, zero)); - // SgStatement* toAdd = new SgStatement(SPF_PARAMETER_OP, NULL, NULL, ex, NULL, NULL); - // stmt_before->insertStmtAfter(*toAdd, *stmt_before->controlParent()); + stmt_before->switchToFile(); + SgVariableSymb* var_symb = new SgVariableSymb(var_name.c_str()); + SgVarRefExp* var = new SgVarRefExp(var_symb); + SgValueExp* zero = new SgValueExp(1337); + SgExprListExp* ex = new SgExprListExp(); + ex->setLhs(new SgExpression(ASSGN_OP, var, zero)); + 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)); } diff --git a/src/ProjectParameters/projectParameters.h b/src/ProjectParameters/projectParameters.h index 36547b7..1181560 100644 --- a/src/ProjectParameters/projectParameters.h +++ b/src/ProjectParameters/projectParameters.h @@ -4,27 +4,37 @@ #include #include #include +#include using ResultSet = std::set>; +enum class MODE +{ + BEFORE, + AFTER +}; + +static std::map> call_sites; + template -static void extract_vars_from_reg(std::set& worklist, - SAPFOR::Argument* reg, - Iterator instr, - Iterator first_instr); +void extract_vars_from_reg(std::set& worklist, + SAPFOR::Argument* reg, + Iterator instr, + Iterator first_instr); template -static void processArgument(std::set& worklist, - SAPFOR::Argument* arg, - Iterator instr, - Iterator first_instr); +void processArgument(std::set& worklist, + SAPFOR::Argument* arg, + Iterator instr, + Iterator first_instr); -static void lookup_for_vars(std::map& where_to_add, - std::set& worklist, - SAPFOR::Instruction* instr, - SAPFOR::BasicBlock* bblock, - const std::map>& fullIR); +void lookup_for_vars(std::set>& where_to_add, + std::set& worklist, + SAPFOR::Instruction* instr, + SAPFOR::BasicBlock* bblock, + FuncInfo* cur_func, + const std::map>& fullIR); void findParameters(ResultSet& foundParameters,