#include #include #include #include #include #include #include #include #include #include #include "../Utils/SgUtils.h" #include "../CFGraph/CFGraph.h" #include "CFGraph/IR.h" #include "Distribution/Array.h" #include "dvm.h" #include "../Utils/errors.h" #include "../GraphCall/graph_calls.h" #include "../GraphCall/graph_calls_func.h" #include "libSage++.h" #include "projectParameters.h" #include "domTree.h" using namespace std; tuple stmtToIR(const map>& CFGraph, SgStatement* stmt) { SgStatement* cur = stmt; while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR) cur = cur->controlParent(); string funcName = ((SgProcHedrStmt*)cur)->nameWithContains(); int stmtID = stmt->id(); for (const auto& [func, bblocks] : CFGraph) { if (func->funcName != funcName) continue; for (auto basicBlock : bblocks) for (auto ins : basicBlock->getInstructions()) if (stmtID == ins->getInstruction()->getOperator()->id()) return make_tuple(func, ins->getInstruction(), basicBlock); } printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return { NULL, NULL, NULL }; } template static 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_) { std::cout << "worklist add: " << arg->getValue() << std::endl; //DEBUG PRINT worklist.insert(arg); } } template static void extract_vars_from_reg(set& worklist, SAPFOR::Argument* reg, Iterator instr, Iterator first_instr) { for (; instr >= first_instr; instr--) { if ((*instr)->getInstruction()->getResult() == reg) { processArgument(worklist, (*instr)->getInstruction()->getArg1(), instr, first_instr); processArgument(worklist, (*instr)->getInstruction()->getArg2(), instr, first_instr); return; } } } static void lookup_for_vars(std::map& where_to_add, set& worklist, SAPFOR::Instruction* instr, SAPFOR::BasicBlock* bblock, 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--) { auto instr = (*cur_instr)->getInstruction(); auto result_arg = instr->getResult(); auto arg1 = instr->getArg1(); auto arg2 = instr->getArg2(); 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++; 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", 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 { //check if variable is modified in called function } } } const auto& RD = bblock->getRD_In(); map group_by_block; for (auto& arg : worklist) { if (RD.count(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) __spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible", arg->getValue().c_str()); else { for (const auto& instr_num : RD.at(arg)) { auto [instr, bblock] = getInstructionAndBlockByNumber(fullIR, instr_num); if (group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num) group_by_block[bblock] = instr; } } } } auto idom = bblock->getIdom(); while (idom != NULL) { if (group_by_block.count(idom)) { lookup_for_vars(where_to_add, worklist, group_by_block[idom], idom, fullIR); return; } idom = idom->getIdom(); } } static void handle_single_allocate(std::map& where_to_add, SgStatement* alloc_statement, const std::map>& fullIR) { auto [func, instr, bblock] = stmtToIR(fullIR, alloc_statement); 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; }); auto alloc_instr = cur_instr; // 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 set worklist; for (int i = 0; i < arrays_num; i++) { auto param_instr = --alloc_instr; auto param_reg = (*param_instr)->getInstruction()->getArg1(); 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) { 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); } static void handle_single_loop(std::map& where_to_add, SgStatement* loop_stmt, const std::map>& fullIR) { auto [func_name, instr, bblock] = stmtToIR(fullIR, loop_stmt); std::cout << "bblock: " << bblock->getNumber() << " instr: " << instr->getNumber() << std::endl; auto cur_instr = bblock->getInstructions().end() - 1; 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); } void findParameters(ResultSet& foundParameters, std::map>& fullIR, const std::map, std::pair>& declaredArrays) { map 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) { for (const auto& ir_block : block->getInstructions()) { auto instr = ir_block->getInstruction(); if (instr->getOperation() == SAPFOR::CFG_OP::F_CALL) { auto func_name = instr->getArg1()->getValue(); auto func_info = name_to_func.find(func_name); if (func_info != name_to_func.end()) call_sites[func_info->second].push_back(instr); } } } SAPFOR::buildDominatorTreeLT(bblocks); for (auto block : bblocks) { if (block->getIdom() != NULL) std::cout << "BB: " << block->getNumber() << " IDOM: " << block->getIdom()->getNumber() << std::endl; } std::cout << "+++++++++++\n"; } 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& alloc_statement : alloc_statements) { handle_single_allocate(where_to_add, alloc_statement, fullIR); } set for_statements; // Find all FOR statements in the program 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() == FOR_NODE) { std::cout << block->getNumber() << std::endl; for_statements.insert(op); } } for (const auto& stmt : for_statements) { handle_single_loop(where_to_add, stmt, fullIR); } for (const auto& [stmt_before, var_name] : 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()); foundParameters.insert(make_tuple(stmt_before->fileName(), stmt_before->lineNumber(), var_name)); } }