#pragma once #include #include #include "../Utils/AstWrapper.h" #include "../Utils/utils.h" #include "../DirectiveProcessing/shadow.h" #include "../GraphLoop/graph_loops.h" static const char* paramNames[] = { "NONE_T", "ARRAY_T", "STRING_ARRAY_T", "STRING_T", "SCALAR_CHAR_T", "SCALAR_BOOL_T", "SCALAR_SHORT_T", "SCALAR_INT_T", "SCALAR_LONG_INT_T", "SCALAR_FLOAT_T", "SCALAR_DOUBLE_T", "SCALAR_CMPLX_FLOAT_T", "SCALAR_CMPLX_DOUBLE_T", "EXTERNAL_T", "UNKNOWN_T" }; typedef enum parF { NONE_T, ARRAY_T, STRING_ARRAY_T, STRING_T, SCALAR_CHAR_T, SCALAR_BOOL_T, SCALAR_SHORT_T, SCALAR_INT_T, SCALAR_LONG_INT_T, SCALAR_FLOAT_T, SCALAR_DOUBLE_T, SCALAR_CMPLX_FLOAT_T, SCALAR_CMPLX_DOUBLE_T, EXTERNAL_T, UNKNOWN_T} paramType; #ifndef IN_BIT #define IN_BIT 16 #endif #ifndef OUT_BIT #define OUT_BIT 256 #endif struct FuncParam { FuncParam() { countOfPars = 0; } void init(const int numPar) { countOfPars = numPar; if (numPar) { parameters.resize(numPar); parametersT.resize(numPar); inout_types.resize(numPar); std::fill(parametersT.begin(), parametersT.end(), NONE_T); std::fill(inout_types.begin(), inout_types.end(), 0); } } void completeParams() { for (int z = 0; z < countOfPars; ++z) if (inout_types[z] == 0) inout_types[z] = IN_BIT; } bool isArgIn(const int num) const { if (num >= countOfPars) return false; else return (inout_types[num] & IN_BIT) != 0; } bool isArgOut(const int num) const { if (num >= countOfPars) return false; else return (inout_types[num] & OUT_BIT) != 0; } bool isArgInOut(const int num) const { if (num >= countOfPars) return false; else return isArgIn(num) && isArgOut(num); } static bool isArgIn(int64_t type) { return (type & IN_BIT) != 0; } static bool isArgOut(int64_t type) { return (type & OUT_BIT) != 0; } static bool isArgInOut(int64_t type) { return isArgIn(type) && isArgOut(type); } std::vector identificators; std::vector parameters; std::vector parametersT; std::vector inout_types; int countOfPars; }; #ifndef IN_BIT #undef IN_BIT #endif #ifndef OUT_BIT #undef OUT_BIT #endif struct NestedFuncCall { std::string CalledFuncName; std::vector> NoOfParamUsedForCall; NestedFuncCall(std::string funcName) : CalledFuncName(funcName) { } NestedFuncCall(std::string funcName, int ParsNum) : CalledFuncName(funcName), NoOfParamUsedForCall(std::vector>(ParsNum)) { } }; struct FuncInfoCallFrom { // std::pair detailCallsFrom; // SgStatement for PROC_STAT, SgExpression for FUNC_CALL, VAR_REF for external calls std::pair pointerDetailCallsFrom; // parent SgStatement* of FUNC_CALL void* parentForPointer; FuncParam actualParams; }; struct FuncInfo { std::string funcName; std::pair linesNum; std::string fileName; Statement *funcPointer; bool isMain; bool isInterface; std::set callsFrom; //calls from this function std::set callsFromV; std::vector callsFromDetailed; std::map> commonBlocks; std::vector callsTo; //calls of this function FuncParam funcParams; std::vector isParamUsedAsIndex; std::vector funcsCalledFromThis; // size = amount of calls in this func; // if (FuncsCalledFromThis[func_call_idx]. // NoOfParamUsedForCall.size() == 0) - no params of cur func used ShadowNode* shadowTreeStart; ShadowNode* shadowTreeEnd; std::map allShadowNodes; std::set allUsedArrays; // real array refs std::set usedArraysWrite; // real array refs std::vector loopsInFunc; std::set linesOfIO; std::set linesOfStop; std::map interfaceBlocks; std::map interfaceSynonims; std::vector entry; // all entry points std::set externalCalls; bool isPure; // does this func or funcs called from this have common block[s] and have no side effects bool doNotInline; bool doNotAnalyze; bool needToInline; bool deadFunction; // for RESOLVE_PAR_REGIONS int inRegion; // 0 - none, 1 - explicit, 2 - implicit, 3 - indirect std::set callRegions; // 0 - default; forall i > 0, i - user region bool isInRegion() { return inRegion == 1 || inRegion == 2; } bool isIndirect() { return inRegion == 3; } // std::vector fullCopiesOfThisFunction; FuncInfo() : doNotInline(false), funcPointer(NULL), doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isPure(false), isMain(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { } FuncInfo(const std::string &funcName, const std::pair &lineNum) : funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(NULL), doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false), isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { } #if !__SPC FuncInfo(const std::string &funcName, const std::pair &lineNum, Statement *pointer) : funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(pointer), doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false), isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { fileName = pointer->fileName(); } #endif std::vector> GetDetailedCallInfo(const std::string &funcName) { std::vector> result; for (int i = 0; i < callsFromDetailed.size(); ++i) { if (callsFromDetailed[i].detailCallsFrom.first == funcName) result.push_back(callsFromDetailed[i].pointerDetailCallsFrom); } return result; } std::string getFuncNameWithContainsByRegion(const uint64_t regionId) { if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end()) return funcName + "_r" + std::to_string(regionId); return funcName; } std::string getFuncNameByRegion(const std::string &shortName, const uint64_t regionId) { if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end()) return shortName + "_r" + std::to_string(regionId); return shortName; } void removeNonDistrArrays() { std::set newUsedArrays; for (auto &elem : allUsedArrays) if (elem->GetDistributeFlagVal() == DIST::DISTR) newUsedArrays.insert(elem); allUsedArrays = newUsedArrays; } bool usesIO() const { return (linesOfIO.size() != 0 || linesOfStop.size() != 0); } std::string getCallName(const std::pair& call_info, const std::string& name, int line) { if (line <= 0) return name; std::set names; for (auto& call : callsFromDetailed) { if (call.pointerDetailCallsFrom == call_info && call.detailCallsFrom.second == line) return call.detailCallsFrom.first; if (call.detailCallsFrom.second == line) if (call.detailCallsFrom.first.find(name) != std::string::npos) names.insert(call.detailCallsFrom.first); } //TODO: detect func call better if (names.size() == 1) return *names.begin(); //try to find in next lvl calls for (auto& call : callsFromDetailed) { if (call.detailCallsFrom.second == line) { std::string name_next = call.detailCallsFrom.first; std::set next, done; for (auto& callFrom : callsFromV) if (callFrom->funcName == name_next) next.insert(callFrom); done = next; while (next.size()) { auto curr = next; next.clear(); for (auto& callFrom : curr) { for (auto& call : callFrom->callsFromDetailed) { if (call.detailCallsFrom.first == name) return call.detailCallsFrom.first; } for (auto& callFromNext : callFrom->callsFromV) { if (done.find(callFromNext) == done.end()) { next.insert(callFromNext); done.insert(callFromNext); } } } } } } return ""; } }; struct CallV { std::string fName; std::string fileName; bool isMain; int inRegion; CallV() : inRegion(0), isMain(false) { } CallV(const std::string &fName) : fName(fName), fileName(""), isMain(false), inRegion(0) { } CallV(const std::string &fName, const std::string &fileName, bool isMain) : fName(fName), fileName(fileName), isMain(isMain), inRegion(0) { } std::string to_string() { return fName + "@" + fileName + "@" + (isMain ? "1" : "0") + "@" + std::to_string(inRegion); } }; void propagateArrayFlags(const std::map> &arrayLinksByFuncCalls, const std::map, std::pair> &declaredArrays, std::map> &SPF_messages); void removeDistrStateFromDeadFunctions(const std::map>& allFuncInfo, const std::map, std::pair>& declaredArrays); bool detectMpiCalls(const std::map>& allFuncInfo, std::map>& SPF_messages); int getLvlCall(FuncInfo* currF, int lvl, const std::string& func, const std::string& file, int line); void compliteArrayUsage(DIST::Arrays& allArraysForRegion, std::map, DIST::Array*>& createdArrays, const std::map>& arrayLinksByFuncCalls, const std::map>& tableOfUniqNamesByArray); void remoteNotUsedArrays(std::map, DIST::Array*>& createdArrays, const std::set& usedArraysAcrossRegions, const std::map>& arrayLinksByFuncCalls);