diff --git a/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.cpp b/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.cpp index fd395dc..7ac33d0 100644 --- a/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.cpp +++ b/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.cpp @@ -1,8 +1,6 @@ -#include "../Utils/leak_detector.h" - +#include #include #include -#include #include #include #include @@ -11,23 +9,202 @@ #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 "../Utils/SgUtils.h" #include "../GraphCall/graph_calls.h" #include "../GraphCall/graph_calls_func.h" +#include "libSage++.h" #include "projectParameters.h" using namespace std; -map< pair, set> - findParameters(const map> &defUseByFunctions, - const map &commonBlocks, - const map> &allFuncInfo) +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) { - map< pair, set> foundParameters; - - - return foundParameters; -} \ No newline at end of file + 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; +} diff --git a/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.h b/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.h index 5a240b0..25e32e4 100644 --- a/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.h +++ b/sapfor/experts/Sapfor_2017/_src/ProjectParameters/projectParameters.h @@ -1,3 +1,24 @@ #pragma once -std::map< std::pair, std::set> findParameters(const std::map> &defUseByFunctions, const std::map &commonBlocks, const std::map> &allFuncInfo); \ No newline at end of file +#include +#include +#include + +using ResultSet = std::set>; + +template +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); + +static void lookup_for_vars(ResultSet& result_set, + std::set& worklist, + SAPFOR::Instruction* instr, + SAPFOR::BasicBlock* bblock, + const std::map>& fullIR); + +ResultSet +findParameters(const std::map>& fullIR, + const std::map, std::pair>& declaredArrays); diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp index 71c2929..ee90345 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp @@ -1865,7 +1865,11 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne else if (curr_regime == RENAME_SYMBOLS) runRenameSymbols(&project, commonBlocks); else if (curr_regime == FIND_PARAMETERS) - parametersOfProject = findParameters(defUseByFunctions, commonBlocks, allFuncInfo); + { + performRDSubst(fullIR, commonBlocks, &project); + parametersOfProject = findParameters(fullIR, declaredArrays); + performRDSubst(fullIR, commonBlocks, &project); + } else if (curr_regime == BUILD_IR) { auto CFG_forFile = buildCFG(commonBlocks, allFuncInfo_IR, SAPFOR::CFG_Settings(0)); @@ -2344,6 +2348,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam case FIX_COMMON_BLOCKS: case TEST_PASS: case SET_IMPLICIT_NONE: + case FIND_PARAMETERS: runAnalysis(*project, curr_regime, false); case SUBST_EXPR_RD_AND_UNPARSE: case SUBST_EXPR_AND_UNPARSE: diff --git a/sapfor/experts/Sapfor_2017/_src/SapforData.h b/sapfor/experts/Sapfor_2017/_src/SapforData.h index 97fc31e..10cb94c 100644 --- a/sapfor/experts/Sapfor_2017/_src/SapforData.h +++ b/sapfor/experts/Sapfor_2017/_src/SapforData.h @@ -168,7 +168,7 @@ std::map filesInfo; // information about open,close,write and re // //for FIND_PARAMETERS -std::map< std::pair, std::set> parametersOfProject; // [file, line] -> set[vars] +std::set> parametersOfProject; // [file, line, varname] // //for GET_MIN_MAX_BLOCK_DIST diff --git a/sapfor/experts/Sapfor_2017/_test/sapfor/parameter/dynamic_array_maximum.f90 b/sapfor/experts/Sapfor_2017/_test/sapfor/parameter/dynamic_array_maximum.f90 new file mode 100644 index 0000000..f49e5e3 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_test/sapfor/parameter/dynamic_array_maximum.f90 @@ -0,0 +1,52 @@ +program dynamic_array_maximum_3d + implicit none + integer :: n1, n2, n3, n4 , k, i, j, l, a + integer :: sum3 + real :: max_element + real, allocatable :: array(:,:,:), array2(:,:,:), array3(:,:,:) + + write(*, *) "Enter 3 integers" + read(*, *) n, m, k + m = 100 + + if (1 .eq. 1) then + a = 3 + else if (2 .eq. 1) then + a = 4 + endif + + m = m + 1 + k = m * 1000 + n * 10 + + allocate(array(n, m + n, k + m + n), & + &array2(k, m + n, k), & + &array3(k, m, k + n)) + + call random_seed() + do i = 1, n1 + do j = 1, m * n1 + do l = 1, k * m * n1 + call random_number(array(i,j,l)) + array(i,j,l) = int(array(i,j,l) * 100) + end do + end do + end do + + max_element = array(1,1,1) + do i = 1, n1 + do j = 1, m + do l = 1, k + max_element = MAX(array(i,j,l), max_element) + end do + end do + end do + deallocate(array, array2, array3) + write(*, *) max_element +end program dynamic_array_maximum_3d + +! function sum3(x, y, z) +! implicit none +! integer :: x, y, z +! integer :: sum3 +! sum3 = x + y + z +! end function sum3