#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" using namespace std; 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 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(ResultSet& result_set, 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 filename = (*f_call_instr)->getInstruction()->getOperator()->fileName(); auto line = (*f_call_instr)->getInstruction()->getOperator()->lineNumber(); __spf_print(1,"Please specify value of variable %s on line %d of file %s", arg1->getValue().c_str(), line, filename); result_set.insert(make_tuple(filename, line, arg1->getValue())); 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() == 0) __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; } } } } for (const auto& [bblock, instr] : group_by_block) { lookup_for_vars(result_set, worklist, instr, bblock, fullIR); } } static void handle_single_allocate(ResultSet& result_set, SAPFOR::Instruction* instr, SAPFOR::BasicBlock* bblock, const std::map>& fullIR) { 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(result_set,worklist, instr, bblock, fullIR); } ResultSet findParameters(const std::map>& fullIR, const std::map, std::pair>& declaredArrays) { ResultSet foundParameters; std::set alloc_statements; for (const auto& elem : declaredArrays) { const auto& array = elem.second.first; assert(array->GetLocation().first == Distribution::arrayLocation::l_LOCAL); // v0.1 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) { auto [instr, bblock] = getInstructionAndBlockByStatement(fullIR, alloc_statement); ResultSet result_set; handle_single_allocate(result_set, instr, bblock, fullIR); } return foundParameters; }