#include "leak_detector.h" #include #include #include #include "../Utils/SgUtils.h" #include "../Utils/utils.h" #include "expr_transform.h" #include "checkpoints.h" using namespace std; enum class typeEvery { TIME, ITER }; static const vector iosNames = { "spf_close_all", "spf_open_all", "spf_inc_num_part" }; static SgStatement* replaceForWithWhile(SgStatement* forSt) { checkNull(forSt, convertFileName(__FILE__).c_str(), __LINE__); auto forStat = isSgForStmt(forSt); checkNull(forStat, convertFileName(__FILE__).c_str(), __LINE__); auto start = forStat->start(); auto end = forStat->end(); auto step = forStat->step(); if (step == NULL) step = new SgValueExp(1); auto stepCalc = CalculateInteger(step->copyPtr()); auto doName = forStat->doName(); checkNull(start, convertFileName(__FILE__).c_str(), __LINE__); checkNull(end, convertFileName(__FILE__).c_str(), __LINE__); SgStatement* insert = forSt->lexPrev(); SgStatement* doWhile = NULL; if (stepCalc->isInteger()) { const int stepValue = stepCalc->valueInteger(); auto cond = (stepValue > 0) ? (*new SgVarRefExp(doName) < end->copy()) : (*new SgVarRefExp(doName) > end->copy()); auto cond2 = (stepValue > 0) ? (*new SgVarRefExp(doName) > end->copy()) : (*new SgVarRefExp(doName) < end->copy()); SgLogIfStmt* logIf = new SgLogIfStmt(cond2, *new SgStatement(EXIT_STMT)); doWhile = new SgWhileStmt(&cond, NULL); insert->insertStmtAfter(*doWhile, *insert->controlParent()); auto insertTo = doWhile->lastNodeOfStmt(); SgStatement* last = forSt->lastNodeOfStmt(); while (forSt->lexNext() != last) { auto body = forSt->lexNext(); insertTo->insertStmtBefore(*body->extractStmt(), *doWhile); } doWhile->insertStmtBefore(*new SgAssignStmt(*new SgVarRefExp(doName), start->copy() - step->copy()), *insert->controlParent()); doWhile->insertStmtAfter(*logIf, *doWhile); doWhile->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(doName), (*new SgVarRefExp(doName) + *step)), *doWhile); doWhile->addComment(forSt->comments()); forSt->extractStmt(); } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return doWhile; } static void checkForToReplace(SgStatement* gotoBlock, SgStatement* goPoint) { //return; auto cp = gotoBlock->controlParent(); while (goPoint->controlParent() != cp) { auto top = goPoint->controlParent(); if (top->variant() == FOR_NODE) goPoint = replaceForWithWhile(top); else goPoint = top; } } static void createModule(SgStatement*& module, const string& name, bool withFile = true) { if (module == NULL) { string full_name = name; if (withFile) full_name += "_" + to_string(current_file_id); module = new SgStatement(MODULE_STMT, NULL, new SgSymbol(MODULE_NAME, full_name.c_str())); addControlEndToStmt(module->thebif); SgStatement* global = current_file->firstStatement(); global->insertStmtAfter(*module, *global); } } static SgType* createArrayCharType(int len, int dim) { if (dim == 0) { auto simpleType = new SgType(*SgTypeChar()); auto lenght = new SgValueExp(len); simpleType->thetype->entry.Template.kind_len = lenght->thellnd; return simpleType; } else { auto arrayType = new SgArrayType(*SgTypeChar()); arrayType->addDimension(new SgValueExp(dim)); auto lenght = new SgValueExp(len); arrayType->baseType()->thetype->entry.Template.kind_len = lenght->thellnd; return arrayType; } } static void findDecls(SgExpression* ex, vector& local, const map& localParams, set& added, set& intentInParams) { if (ex) { if (ex->variant() == VAR_REF) { if (ex->symbol()->variant() == VARIABLE_NAME && localParams.find(ex->symbol()->identifier()) == localParams.end()) { if (added.find(ex->symbol()->identifier()) == added.end() && intentInParams.find(ex->symbol()->identifier()) == intentInParams.end()) { added.insert(ex->symbol()->identifier()); local.push_back(ex); } } } if (ex->variant() == ARRAY_REF) { if (ex->symbol()->variant() == VARIABLE_NAME && added.find(ex->symbol()->identifier()) == added.end() && intentInParams.find(ex->symbol()->identifier()) == intentInParams.end()) { added.insert(ex->symbol()->identifier()); local.push_back(new SgArrayRefExp(*ex->symbol())); } } findDecls(ex->lhs(), local, localParams, added, intentInParams); findDecls(ex->rhs(), local, localParams, added, intentInParams); } } static FuncInfo* findFileInfoByName(SgStatement* func, const vector& allFuncInfo) { FuncInfo* funcI = NULL; for (const auto& funcs : allFuncInfo) if (funcs->funcName == func->symbol()->identifier()) funcI = funcs; checkNull(funcI, convertFileName(__FILE__).c_str(), __LINE__); return funcI; } static void findLocalData(SgStatement* func, SgStatement* end, vector& local, map& localParams, set& added, const vector& allFuncInfo) { SgStatement* start = func->lexNext(); FuncInfo* funcI = findFileInfoByName(func, allFuncInfo); set intentInParams; for (int i = 0; i < funcI->funcParams.countOfPars; ++i) if (funcI->funcParams.isArgIn(i) && !funcI->funcParams.isArgOut(i)) intentInParams.insert(funcI->funcParams.identificators[i]); for (SgStatement* st = start; st != end; st = st->lexNext()) { if (st->variant() == PARAM_DECL) { auto decl = (SgParameterStmt*)st; for (int z = 0; z < decl->numberOfConstants(); ++z) localParams[decl->constant(z)->identifier()] = st; } if (st->variant() == EXTERN_STAT) for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs()) added.insert(ex->lhs()->symbol()->identifier()); } for (SgStatement* st = start; st != end; st = st->lexNext()) { //printf("line %d %s Var %s\n", st->lineNumber(), st->fileName(), tag[st->variant()]); if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90) findDecls(st->expr(0), local, localParams, added, intentInParams); } } static vector findUseOfModules(SgStatement* start, SgStatement* end) { vector ret; for (SgStatement* st = start; st != end; st = st->lexNext()) if (st->variant() == USE_STMT) ret.push_back(st); return ret; } static vector findAllModules() { vector ret; const string old_file = current_file->filename(); for (int z = 0; z < CurrentProject->numberOfFiles(); ++z) { SgFile* file = &CurrentProject->file(z); vector modules; findModulesInFile(file, modules); for (auto& elem : modules) ret.push_back(elem->symbol()->identifier()); } if (SgFile::switchToFile(old_file) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return ret; } static SgExpression* getAttribute(SgExpression* spec, const string& type) { while (spec) { if (spec->lhs() && spec->lhs()->variant() == SPEC_PAIR) { if (spec->lhs()->lhs()->variant() == KEYWORD_VAL) { SgKeywordValExp* val = (SgKeywordValExp*)(spec->lhs()->lhs()); if (val->value() == type) return spec->lhs()->rhs(); } } spec = spec->rhs(); } return NULL; } static SgSymbol* makeVar(const string& name) { return new SgSymbol(VARIABLE_NAME, name.c_str()); } static void insertToOpenClose(const map& needToSave, const vector& names, const vector& closedStatus, const string& iosModule) { int z = 0; map>> useOnlyByFileAndFunc; for (auto& elem : needToSave) { for (int k = 0; k < elem.second.placesOpen.size(); ++k) { auto lastFile = current_file->filename(); SgStatement* currOpen = elem.second.placesOpen[k]; if (!currOpen->switchToFile()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); currOpen->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(makeVar(closedStatus[z])), *new SgValueExp(1)), *currOpen->controlParent()); auto fileN = getAttribute(((SgIOControlStmt*)currOpen)->controlSpecList(), "file"); checkNull(fileN, convertFileName(__FILE__).c_str(), __LINE__); currOpen->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(makeVar(names[z])), *fileN), *currOpen->controlParent()); auto fStat = getFuncStat(currOpen, { MODULE_STMT }); checkNull(fStat, convertFileName(__FILE__).c_str(), __LINE__); useOnlyByFileAndFunc[currOpen->fileName()][fStat].insert(closedStatus[z]); useOnlyByFileAndFunc[currOpen->fileName()][fStat].insert(names[z]); if (SgFile::switchToFile(lastFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } ++z; } z = 0; for (auto& elem : needToSave) { for (int k = 0; k < elem.second.placesClose.size(); ++k) { auto lastFile = current_file->filename(); SgStatement* currClose = elem.second.placesClose[k]; if (!currClose->switchToFile()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); currClose->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(makeVar(closedStatus[z])), *new SgValueExp(0)), *currClose->controlParent()); auto fStat = getFuncStat(currClose, { MODULE_STMT }); checkNull(fStat, convertFileName(__FILE__).c_str(), __LINE__); useOnlyByFileAndFunc[currClose->fileName()][fStat].insert(closedStatus[z]); if (SgFile::switchToFile(lastFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } ++z; } auto lastFile = current_file->filename(); for (auto& byFile : useOnlyByFileAndFunc) { if (SgFile::switchToFile(byFile.first) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& byStat : byFile.second) { vector onlyList; for (auto& elem : byStat.second) onlyList.push_back(new SgVarRefExp(new SgSymbol(VARIABLE_NAME, elem.c_str()))); SgExpression* only = new SgExpression(ONLY_NODE, makeExprList(onlyList), NULL); SgStatement* use = new SgStatement(USE_STMT, NULL, makeVar(iosModule), only, NULL, NULL); byStat.first->insertStmtBefore(*use, *byStat.first); } } if (SgFile::switchToFile(lastFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } static bool createForIOs(const map& filesInfo, SgStatement* func) { SgStatement* moduleF = NULL; map needToSave; for (auto& elem : filesInfo) { if (elem.second.placesClose.size() != elem.second.placesOpen.size()) if (elem.second.placesClose.size() > 0 && elem.second.placesOpen.size() > 0) needToSave[elem.first] = elem.second; if (elem.second.placesClose.size() == 0 && elem.second.placesWrite.size() > 0 && elem.second.placesRead.size() == 0) needToSave[elem.first] = elem.second; } if (needToSave.size() == 0) return false; const string iosModule = "spf_module_ios"; createModule(moduleF, iosModule, false); vector closedStatus; vector closedStatusInit; SgSymbol* counter = new SgSymbol(VARIABLE_NAME, "num_part", SgTypeInt(), func); vector names; for (auto& elem : needToSave) { closedStatus.push_back(new SgSymbol(VARIABLE_NAME, ("spf_state_" + to_string(elem.first)).c_str(), SgTypeInt(), func)); closedStatusInit.push_back(new SgValueExp(0)); names.push_back(new SgSymbol(VARIABLE_NAME, ("spf_name_" + to_string(elem.first)).c_str(), createArrayCharType(32, 0), func)); } makeDeclaration(moduleF, closedStatus, &closedStatusInit); makeDeclaration(moduleF, names); makeDeclaration(moduleF, { counter }, &closedStatusInit); moduleF->lastNodeOfStmt()->insertStmtBefore(*new SgStatement(CONTAINS_STMT), *moduleF); SgProcHedrStmt* close = new SgProcHedrStmt(iosNames[0].c_str()); SgProcHedrStmt* open = new SgProcHedrStmt(iosNames[1].c_str()); SgProcHedrStmt* inc = new SgProcHedrStmt(iosNames[2].c_str()); moduleF->lastNodeOfStmt()->insertStmtBefore(*close, *moduleF); moduleF->lastNodeOfStmt()->insertStmtBefore(*open, *moduleF); moduleF->lastNodeOfStmt()->insertStmtBefore(*inc, *moduleF); inc->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(counter), *new SgVarRefExp(counter) + *new SgValueExp(1)), *inc); int z = 0; for (auto& elem : needToSave) { SgIfStmt* ifstat = new SgIfStmt(*new SgVarRefExp(closedStatus[z]) != *new SgValueExp(0), *new SgIOControlStmt(CLOSE_STAT, *new SgValueExp(elem.first))); ifstat->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(closedStatus[z]), *new SgValueExp(0)), *ifstat); close->insertStmtAfter(*ifstat, *close); ++z; } z = 0; auto sSTR = new SgSymbol(FUNCTION_NAME, "TO_STR", createArrayCharType(32, 0), moduleF); auto trim = new SgSymbol(FUNCTION_NAME, "TRIM"); for (auto& elem : needToSave) { vector listSpec; /*listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("iostat"), *iostat)); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("status"), *new SgValueExp("old")));*/ auto fCall = new SgFunctionCallExp(*trim, *new SgVarRefExp(names[z])); auto fCall2 = new SgFunctionCallExp(*trim, *new SgFunctionCallExp(*sSTR, *new SgVarRefExp(counter))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("file"), *new SgExpression(CONCAT_OP, fCall, fCall2))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("unit"), *new SgValueExp(elem.first))); SgIfStmt* ifstat = new SgIfStmt(*new SgVarRefExp(closedStatus[z]) == *new SgValueExp(0), *new SgIOControlStmt(OPEN_STAT, *makeExprList(listSpec, false))); ifstat->insertStmtAfter(*new SgAssignStmt(*new SgVarRefExp(closedStatus[z]), *new SgValueExp(1)), *ifstat); open->insertStmtAfter(*ifstat, *open); ++z; } auto k_par = new SgSymbol(VARIABLE_NAME, "k"); SgFuncHedrStmt* str_func = new SgFuncHedrStmt(*sSTR); moduleF->lastNodeOfStmt()->insertStmtBefore(*str_func, *moduleF); str_func->AddArg(*new SgVarRefExp(k_par)); str_func->setExpression(0, NULL); //bad solution! str_func->insertStmtAfter(*makeDeclaration(NULL, { sSTR }), *str_func); str_func->lastNodeOfStmt()->insertStmtBefore(*new SgInputOutputStmt(WRITE_STAT, *makeExprList({ new SgKeywordValExp("*"), new SgVarRefExp(sSTR)}, false), *new SgVarRefExp(k_par)), *str_func); SgAssignStmt* adjustl = new SgAssignStmt(*new SgVarRefExp(sSTR), *new SgFunctionCallExp(*new SgSymbol(FUNCTION_NAME, "ADJUSTL"), *new SgVarRefExp(sSTR))); str_func->lastNodeOfStmt()->insertStmtBefore(*adjustl, *str_func); vector namesS, closedStatusS; for (int z = 0; z < names.size(); ++z) { namesS.push_back(names[z]->identifier()); closedStatusS.push_back(closedStatus[z]->identifier()); } insertToOpenClose(needToSave, namesS, closedStatusS, iosModule); moduleF->insertStmtAfter(*new SgImplicitStmt(NULL), *moduleF); return true; } struct cpInfo { int line = -1; int every = 60; int numOfFiles = 2; int unitNum = 789; typeEvery type = typeEvery::ITER; }; static bool findSpfCpDir(SgFile* file, map& info) { bool found = false; int numF = file->numberOfFunctions(); for (int z = 0; z < numF; ++z) { SgStatement* func = file->functions(z); for (SgStatement* st = func; st != func->lastNodeOfStmt(); st = st->lexNext()) { if (st->variant() == CONTAINS_STMT) break; if (!isSgExecutableStatement(st)) continue; vector cpDirs = getAttributes(st, set{ SPF_CHECKPOINT_DIR }); if (cpDirs.size() == 1) { found = true; cpInfo currInfo; currInfo.line = st->lineNumber(); SgExpression* ex = cpDirs[0]->expr(0); while (ex) { if (ex->lhs()) { int var = ex->lhs()->variant(); if (var == SPF_INTERVAL_OP) { int type = ex->lhs()->lhs()->variant(); if (!ex->lhs()->rhs()->isInteger()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); int interval = ex->lhs()->rhs()->valueInteger(); if (type == SPF_ITER_OP) { currInfo.type = typeEvery::ITER; currInfo.every = interval; } else if (type == SPF_TIME_OP) { currInfo.type = typeEvery::TIME; currInfo.every = interval; } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else if (var == SPF_FILES_COUNT_OP) { if (!ex->lhs()->lhs()->isInteger()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); currInfo.numOfFiles = ex->lhs()->lhs()->valueInteger(); } } ex = ex->rhs(); } info[currInfo.line] = currInfo; } else if (cpDirs.size() > 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); deleteAttributes(st, set{ SPF_CHECKPOINT_DIR }); } } return found; } static void fillToProcess(FuncInfo* funcI, set>& toProcess) { int oldSize = toProcess.size(); for (int k = 0; k < funcI->callsTo.size(); k++) { pair n(funcI, funcI->callsTo[k]); toProcess.insert(n); if (toProcess.size() != oldSize) { oldSize = toProcess.size(); fillToProcess(funcI->callsTo[k], toProcess); } } } //TODO: reverse if 'before' == false static int insertInitNamesOfFiles(const int numOfFiles, const string& additional, SgSymbol* files, SgArrayRefExp* journal, SgStatement* insert, bool before = true) { int maxFileLen = -1; string tmp; for (int z = 1; z <= numOfFiles; ++z) { tmp = "spf_cp_file_" + to_string(z) + additional; maxFileLen = std::max(maxFileLen, (int)(tmp.size() + 1)); if (insert) { if (before) insert->insertStmtBefore(*new SgAssignStmt(*new SgArrayRefExp(*files, *new SgValueExp(z)), *new SgValueExp(tmp.c_str())), *insert->controlParent()); else insert->insertStmtAfter(*new SgAssignStmt(*new SgArrayRefExp(*files, *new SgValueExp(z)), *new SgValueExp(tmp.c_str())), *insert->controlParent()); } } tmp = "spf_cp_journal" + additional; if (insert) { if (before) insert->insertStmtBefore(*new SgAssignStmt(*journal, *new SgValueExp(tmp.c_str())), *insert->controlParent()); else insert->insertStmtAfter(*new SgAssignStmt(*journal, *new SgValueExp(tmp.c_str())), *insert->controlParent()); } return maxFileLen; } static void replaceExprByExprInExpr(SgExpression* expr, SgExpression* from, SgExpression* to) { map collection; if (!expr) return; if (isEqExpressions(expr->rhs(), from, collection)) expr->setRhs(to); if (isEqExpressions(expr->lhs(), from, collection)) expr->setLhs(to); replaceExprByExprInExpr(expr->rhs(), from, to); replaceExprByExprInExpr(expr->lhs(), from, to); } static void replaceExprByExprInSt(SgStatement* st, SgExpression* from, SgExpression* to) { map collection; for (int i = 0; i < 3; i++) { SgExpression* expr = st->expr(i); if (!expr) continue; if (isEqExpressions(expr, from, collection)) st->setExpression(i, to); if (isEqExpressions(expr->rhs(), from, collection)) expr->setRhs(to); if (isEqExpressions(expr->lhs(), from, collection)) expr->setLhs(to); else { replaceExprByExprInExpr(expr->rhs(), from, to); replaceExprByExprInExpr(expr->lhs(), from, to); } } } static SgStatement* createOpenJ_old(SgExpression* iostat, SgArrayRefExp* journal, SgExpression& unit) { vector listSpec; listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("iostat"), *iostat)); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("status"), *new SgValueExp("old"))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("file"), *journal)); listSpec.push_back(&unit); SgIOControlStmt* openJ_old = new SgIOControlStmt(OPEN_STAT, *makeExprList(listSpec, false)); return openJ_old; } static SgStatement* createOpen(SgExpression* iostat, SgSymbol* files, SgExpression* fileIdx, SgExpression& unit) { vector listSpec; listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("form"), *new SgValueExp("unformatted"))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("iostat"), *iostat)); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("status"), *new SgValueExp("old"))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("file"), *new SgArrayRefExp(*files, *fileIdx))); listSpec.push_back(&unit); SgIOControlStmt* open = new SgIOControlStmt(OPEN_STAT, *makeExprList(listSpec, false)); return open; } static string mergedChar(const string& l, const string& r) { return l + "_" + r; } static SgSymbol* renamedNewSymb(SgSymbol* oldSymb, const char* prefix) { const string result = mergedChar(prefix, oldSymb->identifier()); SgSymbol* newSymb = new SgSymbol(oldSymb->variant(), result.c_str(), oldSymb->type(), oldSymb->scope()); return newSymb; } static void renameEx(SgExpression* sizeEx, const char* funcName) { if (sizeEx->variant() == CONST_REF) { SgSymbol* symbSize = renamedNewSymb(sizeEx->symbol(), funcName); sizeEx->setSymbol(symbSize); } if (sizeEx->lhs()) renameEx(sizeEx->lhs(), funcName); if (sizeEx->rhs()) renameEx(sizeEx->rhs(), funcName); } static void findSizeEx(SgExpression* sizeEx, const map& moduleStmts, const map& moduleParamStmts, SgStatement* proc_moduleF, set& addedModuleParams, SgStatement* borderStmt) { if (sizeEx->variant() == CONST_REF) { if (moduleParamStmts.count(sizeEx->symbol()->identifier()) == 1 && addedModuleParams.count(sizeEx->symbol()->identifier()) == 0) { auto decl = (SgParameterStmt*)moduleParamStmts.at(sizeEx->symbol()->identifier()); SgStatement* copyParamStmt = moduleParamStmts.at(sizeEx->symbol()->identifier())->copyPtr(); borderStmt->insertStmtBefore(*copyParamStmt, *proc_moduleF); if (moduleStmts.count(sizeEx->symbol()->identifier())) { SgStatement* copyStmt = moduleStmts.at(sizeEx->symbol()->identifier())->copyPtr(); copyParamStmt->insertStmtBefore(*copyStmt, *proc_moduleF); borderStmt = copyStmt; } else borderStmt = copyParamStmt; addedModuleParams.insert(sizeEx->symbol()->identifier()); findSizeEx(decl->value(0), moduleStmts, moduleParamStmts, proc_moduleF, addedModuleParams, borderStmt); } } if (sizeEx->lhs()) findSizeEx(sizeEx->lhs(), moduleStmts, moduleParamStmts, proc_moduleF, addedModuleParams, borderStmt); if (sizeEx->rhs()) findSizeEx(sizeEx->rhs(), moduleStmts, moduleParamStmts, proc_moduleF, addedModuleParams, borderStmt); } static void processCommonStmt(SgStatement* st, set& commonVariables) { if (st->expr(0)) { SgExpression* ex = st->expr(0)->lhs(); while (ex && ex->lhs()) { auto lhs = ex->lhs(); commonVariables.insert(lhs->sunparse()); ex = ex->rhs(); } } } static void processVarStmt(SgStatement* st, map& moduleStmts, const char* funcName, const set& inFuncParam) { SgExpression* ex = st->expr(0); SgExpression* lhs = NULL; SgStatement* baseStmt = st->copyPtr(); baseStmt->expr(0)->setLhs(NULL); baseStmt->expr(0)->setRhs(NULL); baseStmt->setExpression(2, NULL); while (ex && ex->lhs()) { lhs = ex->lhs(); if (inFuncParam.count(lhs->symbol()->identifier())) { ex = ex->rhs(); continue; } const string result = mergedChar(funcName, lhs->symbol()->identifier()); SgSymbol* symb = new SgSymbol(lhs->symbol()->variant(), result.c_str(), lhs->symbol()->type(), lhs->symbol()->scope()); SgExpression* newExpr = new SgExpression(lhs->variant()); newExpr->setSymbol(symb); if (lhs->variant() == ARRAY_REF) { SgExpression* newArraySizeExpr = lhs->lhs()->copyPtr(); SgExpression* sizeEx = newArraySizeExpr; SgExpression* sizeLhs; while (sizeEx && sizeEx->lhs()) { sizeLhs = sizeEx->lhs(); renameEx(sizeLhs, funcName); sizeEx = sizeEx->rhs(); } newExpr->setLhs(newArraySizeExpr); } SgStatement* moduleStmt = baseStmt->copyPtr(); moduleStmt->setExpression(0, newExpr); SgExpression* typeExpr = st->expr(1)->copyPtr(); moduleStmt->setExpression(1, typeExpr); moduleStmts[newExpr->symbol()->identifier()] = moduleStmt; ex = ex->rhs(); } } static void processParamStmt(SgStatement* st, map& moduleParamStmts, const char* funcName) { auto decl = (SgParameterStmt*)st; int n = decl->numberOfConstants(); for (int i = 0; i < n; ++i) { SgSymbol* constSymb = renamedNewSymb(decl->constant(i), funcName); SgExpression* constExpr = new SgExpression(CONST_REF, NULL, NULL, constSymb); SgExpression* valueExpr = decl->value(i)->copyPtr(); renameEx(valueExpr, funcName); SgConstantSymb* paramSymb = new SgConstantSymb(constSymb->identifier(), *decl->controlParent(), *valueExpr); SgParameterStmt* paramSt = new SgParameterStmt(); paramSt->addConstant(paramSymb); moduleParamStmts[constSymb->identifier()] = paramSt; } } static void processExternStmt(SgStatement* st, set& externVars) { if (st->expr(0)) { SgExpression* ex = st->expr(0); SgExpression* lhs; while (ex && ex->lhs()) { lhs = ex->lhs(); externVars.insert(lhs->sunparse()); ex = ex->rhs(); } } } static void processVarBlock(SgStatement* func, SgStatement* firstExec, map& moduleStmts, map& moduleParamStmts, set& commonVariables, set& externVars, FuncInfo* funcFrom, const set& inFuncParam = { }) { const char* funcName = func->symbol()->identifier(); for (SgStatement* st = func->lexNext(); st != firstExec; st = st->lexNext()) { if (st->variant() == COMM_STAT) processCommonStmt(st, commonVariables); else if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90) processVarStmt(st, moduleStmts, funcName, inFuncParam); else if (st->variant() == PARAM_DECL) processParamStmt(st, moduleParamStmts, funcName); else if (st->variant() == EXTERN_STAT) processExternStmt(st, externVars); } } static void insertStmtToModule(const map& moduleStmts, const map& moduleParamStmts, set& addedModuleParams, const set& commonVariables, SgStatement* proc_moduleF, set& localVarNoParams, const set& externVars, const size_t prefixLen) { SgStatement* endProcModuleF = proc_moduleF->lastNodeOfStmt(); SgStatement* borderStmt = new SgStatement(VAR_DECL); proc_moduleF->insertStmtAfter(*borderStmt, *proc_moduleF); for (auto& stat : moduleStmts) { const auto& varName = stat.first; SgStatement* varStmt = stat.second; string varNameNoPref = varName; varNameNoPref.erase(0, prefixLen + 1); if (commonVariables.count(varNameNoPref) == 0 && moduleParamStmts.count(varName) == 0 && externVars.count(varNameNoPref) == 0) { localVarNoParams.insert(varNameNoPref); endProcModuleF->insertStmtBefore(*varStmt, *proc_moduleF); if (varStmt->expr(0)->variant() == ARRAY_REF) { SgExpression* arraySizeExpr = varStmt->expr(0)->lhs(); SgExpression* sizeEx = arraySizeExpr; SgExpression* sizeLhs; while (sizeEx && sizeEx->lhs()) { sizeLhs = sizeEx->lhs(); findSizeEx(sizeLhs, moduleStmts, moduleParamStmts, proc_moduleF, addedModuleParams, borderStmt); sizeEx = sizeEx->rhs(); } } } } borderStmt->deleteStmt(); } static SgStatement* createLoadBlock(const vector& loadS, FuncInfo*& funcI, SgExpression* iostat, SgArrayRefExp* journal, SgExpression& frmt, SgExpression& unit, SgSymbol* files, SgExpression* fileIdx, const int numOfFiles, const vector& profS, SgExpression& frmtProf, SgExpression& unitNull, SgStatement* profCallS, SgStatement* profCallE, const set& localVarNoParams, const map& moduleStmts, const set& commonVariables, bool createdModuleForIO, const vector& moduleNames, const int unitNum, const string& baseFunc, vector>& chainLocalVarNoParams, bool isBaseFunc = true, SgSymbol* procLabelSymb = NULL) { const char* funcName = funcI->funcName.c_str(); vector insertToLoadS; SgStatement* loadBlock = new SgIfStmt(*new SgVarRefExp(loadS[0]) == *new SgValueExp(1)); //*new SgVarRefExp(loadS[0]) loadBlock->addComment("! LOAD CHECKPOINT\n"); if (funcI->isMain) { SgAssignStmt* init = new SgAssignStmt(*new SgVarRefExp(loadS[0]), *new SgValueExp(0)); insertToLoadS.push_back(init); insertToLoadS.push_back(createOpenJ_old(iostat, journal, unit)); } vector insertToifLoadOk; SgIfStmt* ifLoadOk = new SgIfStmt(*iostat == *new SgValueExp(0)); insertToLoadS.push_back(ifLoadOk); if (funcI->isMain) { SgInputOutputStmt* read = new SgInputOutputStmt(READ_STAT, *makeExprList({ &frmt, &unit }, false), *fileIdx); //*makeExprList({ fileIdx, labelIdx }) insertToifLoadOk.push_back(read); insertToifLoadOk.push_back(new SgIOControlStmt(CLOSE_STAT, unit)); insertToifLoadOk.push_back(createOpen(iostat, files, fileIdx, unit)); } SgIfStmt* ifLoadOk1 = new SgIfStmt(*iostat == *new SgValueExp(0)); //, *new SgIOControlStmt(CLOSE_STAT, unit) insertToifLoadOk.push_back(ifLoadOk1); if (funcI->isMain) { SgAssignStmt* init = new SgAssignStmt(*new SgVarRefExp(loadS[0]), *new SgValueExp(1)); ifLoadOk1->insertStmtAfter(*init, *ifLoadOk1); } if (isBaseFunc) { ifLoadOk1->insertStmtAfter(*new SgIOControlStmt(CLOSE_STAT, unit), *ifLoadOk1); ifLoadOk1->insertStmtAfter(*new SgIfStmt(*fileIdx == *new SgValueExp(numOfFiles + 1), *new SgAssignStmt(*fileIdx, *new SgValueExp(1))), *ifLoadOk1); ifLoadOk1->insertStmtAfter(*new SgAssignStmt(*fileIdx, *fileIdx + *new SgValueExp(1)), *ifLoadOk1); } ifLoadOk1->addComment("! LOAD DATA FROM CHECKPOINT\n"); vector commentArgs; commentArgs.push_back(new SgValueExp(" SECONDS")); commentArgs.push_back(&(*new SgVarRefExp(profS[1]) - *new SgVarRefExp(profS[0]))); commentArgs.push_back(new SgArrayRefExp(*files, *fileIdx)); commentArgs.push_back(new SgValueExp("SPF CHECKPOINT LOADED FROM ")); ifLoadOk1->insertStmtAfter(*new SgInputOutputStmt(WRITE_STAT, *makeExprList({ &frmtProf, &unitNull }, false), *makeExprList(commentArgs, false)), *ifLoadOk1); ifLoadOk1->insertStmtAfter(*profCallE->copyPtr(), *ifLoadOk1); // insert copy_block for (auto localVar : localVarNoParams) { SgSymbol* leftSymb = new SgSymbol(VARIABLE_NAME, localVar.c_str()); SgExpression* leftEx = new SgVarRefExp(leftSymb); SgSymbol* rightSymb = renamedNewSymb(leftSymb, funcName); SgExpression* rightEx = new SgVarRefExp(rightSymb); ifLoadOk1->insertStmtAfter(*new SgAssignStmt(*leftEx, *rightEx), *ifLoadOk1); } //open all files if (createdModuleForIO) { SgCallStmt* call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, iosNames[1].c_str())); ifLoadOk1->insertStmtAfter(*call, *ifLoadOk1); } //READ LOCAL DATA vector varNames; if (moduleStmts.size()) { vector variablesVec; for (auto localVar : localVarNoParams) { const char* varName = localVar.c_str(); const string varNameWithPref = mergedChar(funcName, varName); SgSymbol* symbVar = new SgSymbol(VARIABLE_NAME, varNameWithPref.c_str()); SgExpression* exVar = new SgVarRefExp(symbVar); variablesVec.push_back(exVar); varNames.push_back(varNameWithPref); } auto dataRead = new SgInputOutputStmt(READ_STAT, unit, *makeExprList(variablesVec, false)); ifLoadOk1->insertStmtAfter(*dataRead, *ifLoadOk1); } chainLocalVarNoParams.push_back(varNames); if (!isBaseFunc) { SgExpression* procLabelExpr = new SgVarRefExp(procLabelSymb); auto labelRead = new SgInputOutputStmt(READ_STAT, unit, *procLabelExpr); ifLoadOk1->insertStmtAfter(*labelRead, *ifLoadOk1); } //READ from modules for (auto& mod : moduleNames) { SgCallStmt* call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, ("spf_cp_" + mod).c_str())); call->addArg(*new SgValueExp(unitNum)); call->addArg(*new SgValueExp(0)); ifLoadOk1->insertStmtAfter(*call, *ifLoadOk1); } //READ COMMON DATA if (funcI->isMain) if (commonVariables.size()) { vector commanVariablesVec; for (auto commanVar : commonVariables) { SgSymbol* symbCommon = new SgSymbol(VARIABLE_NAME, commanVar.c_str()); SgExpression* exCommon = new SgVarRefExp(symbCommon); commanVariablesVec.push_back(exCommon); } auto commonDataRead = new SgInputOutputStmt(READ_STAT, unit, *makeExprList(commanVariablesVec, false)); ifLoadOk1->insertStmtAfter(*commonDataRead, *ifLoadOk1); } ifLoadOk1->insertStmtAfter(*profCallS->copyPtr(), *ifLoadOk1); for (int z = insertToLoadS.size() - 1; z >= 0; --z) loadBlock->insertStmtAfter(*insertToLoadS[z], *loadBlock); for (int z = insertToifLoadOk.size() - 1; z >= 0; --z) ifLoadOk->insertStmtAfter(*insertToifLoadOk[z], *ifLoadOk); return loadBlock; } static SgSymbol* createLabel(const string namelabel, SgStatement*& proc_moduleF) { SgSymbol* procLabelSymb = new SgSymbol(VARIABLE_NAME, namelabel.c_str(), SgTypeInt(), proc_moduleF); SgExpression* procLabel0 = new SgValueExp(0); vector vecLabelSymb = { procLabelSymb }; vector vecLabel0 = { procLabel0 }; makeDeclaration(proc_moduleF, vecLabelSymb, &vecLabel0); return procLabelSymb; } static SgStatement* createSaveBlock(const vector& loadS, FuncInfo*& funcI, SgExpression* iostat, SgArrayRefExp* journal, SgExpression& frmt, SgExpression& unit, SgSymbol* files, SgExpression* fileIdx, const int numOfFiles, const vector& profS, SgExpression& frmtProf, SgExpression& unitNull, SgStatement* profCallS, SgStatement* profCallE, const set& localVarNoParams, const map& moduleStmts, const set& commonVariables, bool createdModuleForIO, const vector& moduleNames, const int unitNum, const vector>& chainLocalVarNoParams, const vector& chainLabel) { SgStatement* storeBlock = new SgIfStmt((SgExpression*)NULL); vector listSpec; listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("form"), *new SgValueExp("unformatted"))); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("iostat"), *iostat)); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("file"), *new SgArrayRefExp(*files, *fileIdx))); listSpec.push_back(&unit); SgIOControlStmt* open = new SgIOControlStmt(OPEN_STAT, *makeExprList(listSpec, false)); storeBlock->insertStmtAfter(*open, *storeBlock); SgIfStmt* ifStoreOk = new SgIfStmt(*iostat == *new SgValueExp(0)); open->insertStmtAfter(*ifStoreOk, *storeBlock); ifStoreOk->insertStmtAfter(*new SgIfStmt(*fileIdx == *new SgValueExp(numOfFiles + 1), *new SgAssignStmt(*fileIdx, *new SgValueExp(1))), *ifStoreOk); ifStoreOk->insertStmtAfter(*new SgAssignStmt(*fileIdx, *fileIdx + *new SgValueExp(1)), *ifStoreOk); ifStoreOk->addComment(("! STORE DATA TO CHECKPOINT " + to_string(localVarNoParams.size() + commonVariables.size()) + " items\n").c_str()); //commentArgs.clear(); vector commentArgs; commentArgs.push_back(new SgValueExp(" SECONDS")); commentArgs.push_back(&(*new SgVarRefExp(profS[1]) - *new SgVarRefExp(profS[0]))); commentArgs.push_back(new SgArrayRefExp(*files, *fileIdx)); commentArgs.push_back(new SgValueExp("SPF CHECKPOINT STORED TO ")); ifStoreOk->insertStmtAfter(*new SgInputOutputStmt(WRITE_STAT, *makeExprList({ &frmtProf, &unitNull }, false), *makeExprList(commentArgs, false)), *ifStoreOk); ifStoreOk->insertStmtAfter(profCallE->copy(), *ifStoreOk); SgStatement* assign = ifStoreOk->lexNext(); //open all files if (createdModuleForIO) { SgCallStmt* call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, iosNames[1].c_str())); ifStoreOk->insertStmtAfter(*call, *ifStoreOk); } //WRITE from modules for (auto& mod : moduleNames) { SgCallStmt* call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, ("spf_cp_" + mod).c_str())); call->addArg(*new SgValueExp(unitNum)); call->addArg(*new SgValueExp(1)); ifStoreOk->insertStmtAfter(*call, *ifStoreOk); } //close and inc if (createdModuleForIO) { SgCallStmt* call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, iosNames[2].c_str())); ifStoreOk->insertStmtAfter(*call, *ifStoreOk); call = new SgCallStmt(*new SgSymbol(FUNCTION_NAME, iosNames[0].c_str())); ifStoreOk->insertStmtAfter(*call, *ifStoreOk); } if (moduleStmts.size()) { vector variablesVec; for (auto localVar : localVarNoParams) { const char* varName = localVar.c_str(); const string varNameWithPref = mergedChar(funcI->funcName.c_str(), varName); SgSymbol* symbVar = new SgSymbol(VARIABLE_NAME, varNameWithPref.c_str()); SgExpression* exVar = new SgVarRefExp(symbVar); variablesVec.push_back(exVar); } auto dataWrite = new SgInputOutputStmt(WRITE_STAT, unit, *makeExprList(variablesVec, false)); ifStoreOk->insertStmtAfter(*dataWrite, *ifStoreOk); } for (size_t i = 0; i < chainLabel.size(); i++) { if (!chainLocalVarNoParams[i].empty()) { vector variablesVec; for (auto localVar : chainLocalVarNoParams[i]) { const char* varNameWithPref = localVar.c_str(); SgSymbol* symbVar = new SgSymbol(VARIABLE_NAME, varNameWithPref); SgExpression* exVar = new SgVarRefExp(symbVar); variablesVec.push_back(exVar); } auto dataWrite = new SgInputOutputStmt(WRITE_STAT, unit, *makeExprList(variablesVec, false)); ifStoreOk->insertStmtAfter(*dataWrite, *ifStoreOk); } SgSymbol* procLabelSymb = new SgSymbol(VARIABLE_NAME, chainLabel[i].c_str()); SgExpression* procLabelExpr = new SgVarRefExp(procLabelSymb); auto labelRead = new SgInputOutputStmt(WRITE_STAT, unit, *procLabelExpr); ifStoreOk->insertStmtAfter(*labelRead, *ifStoreOk); } if (commonVariables.size()) { vector commanVariablesVec; for (auto commanVar : commonVariables) { SgSymbol* symbCommon = new SgSymbol(VARIABLE_NAME, commanVar.c_str()); SgExpression* exCommon = new SgVarRefExp(symbCommon); commanVariablesVec.push_back(exCommon); } auto commonDataWrite = new SgInputOutputStmt(WRITE_STAT, unit, *makeExprList(commanVariablesVec, false)); ifStoreOk->insertStmtAfter(*commonDataWrite, *ifStoreOk); } // insert copy_block for (auto localVar : localVarNoParams) { SgSymbol* rightSymb = new SgSymbol(VARIABLE_NAME, localVar.c_str()); SgExpression* rightEx = new SgVarRefExp(rightSymb); SgSymbol* leftSymb = renamedNewSymb(rightSymb, funcI->funcName.c_str()); SgExpression* leftEx = new SgVarRefExp(leftSymb); ifStoreOk->insertStmtAfter(*new SgAssignStmt(*leftEx, *rightEx), *ifStoreOk); } listSpec.clear(); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("iostat"), *iostat)); listSpec.push_back(&SgAssignOp(*new SgKeywordValExp("file"), *journal)); listSpec.push_back(&unit); SgIOControlStmt* openJ_new = new SgIOControlStmt(OPEN_STAT, *makeExprList(listSpec, false)); assign->insertStmtBefore(*new SgIOControlStmt(CLOSE_STAT, unit), *ifStoreOk); assign->insertStmtBefore(*openJ_new, *ifStoreOk); assign->insertStmtBefore(*new SgInputOutputStmt(WRITE_STAT, *makeExprList({ &frmt, &unit }, false), *fileIdx), *ifStoreOk); assign->insertStmtBefore(*new SgIOControlStmt(CLOSE_STAT, unit), *ifStoreOk); ifStoreOk->insertStmtAfter(profCallS->copy(), *ifStoreOk); return storeBlock; } static void saveVarToModule(const set& localVarNoParams, SgStatement* callPU, const char* funcName, SgSymbol* procLabelSymb, const int labNum) { for (auto localVar : localVarNoParams) { SgSymbol* rightSymb = new SgSymbol(VARIABLE_NAME, localVar.c_str()); SgExpression* rightEx = new SgVarRefExp(rightSymb); SgSymbol* leftSymb = renamedNewSymb(rightSymb, funcName); SgExpression* leftEx = new SgVarRefExp(leftSymb); callPU->insertStmtBefore(*new SgAssignStmt(*leftEx, *rightEx), *callPU->controlParent()); } SgExpression* procLabelExpr = new SgVarRefExp(procLabelSymb); SgExpression* labNumExpr = new SgValueExp(labNum); callPU->insertStmtBefore(*new SgAssignStmt(*procLabelExpr, *labNumExpr), *callPU->controlParent()); } static void processAllCalls(SgStatement* firstExec, const string funcToName, const string funcFromName, SgStatement* gotoBlock, const set localVarNoParams, SgSymbol* procLabelSymb) { SgStatement* execStmt = firstExec; while (execStmt && isSgExecutableStatement(execStmt)) { if (execStmt->variant() == PROC_STAT && execStmt->symbol()->identifier() == funcToName) { const int labNum = getNextFreeLabel(); auto nextPULabel = new SgLabel(labNum); execStmt->setLabel(*nextPULabel); SgStatement* gotoNextPU = new SgIfStmt(*new SgVarRefExp(procLabelSymb) == *new SgValueExp(labNum)); gotoNextPU->insertStmtAfter(*new SgGotoStmt(*nextPULabel), *gotoNextPU); gotoBlock->insertStmtBefore(*gotoNextPU, *gotoBlock); saveVarToModule(localVarNoParams, execStmt, funcFromName.c_str(), procLabelSymb, labNum); checkForToReplace(gotoBlock, execStmt); } execStmt = execStmt->lexNext(); } } static void processInFuncParam(FuncInfo* funcI, set& inFuncParam) { for (int i = 0; i < funcI->funcParams.countOfPars; ++i) if (funcI->funcParams.isArgIn(i) && !funcI->funcParams.isArgOut(i)) inFuncParam.insert(funcI->funcParams.identificators[i]); } static SgStatement* getFirstExecStat(SgStatement* func) { SgStatement* firstExec = func->lexNext(); SgStatement* last = func->lastNodeOfStmt(); while (firstExec && firstExec != last && !isSgExecutableStatement(firstExec)) { firstExec = firstExec->lastNodeOfStmt(); firstExec = firstExec->lexNext(); } return firstExec; } static void processFunctionCallChain(SgStatement* func, const vector& allFuncInfo, SgStatement* moduleF, const vector& loadS, SgExpression* iostat, SgArrayRefExp* journal, SgExpression& frmt, SgExpression& unit, SgSymbol* files, SgExpression* fileIdx, const int every, const int numOfFiles, const string additional, const vector profS, SgExpression& frmtProf, SgExpression& unitNull, const int unitNum, bool createdModuleForIO, const vector& moduleNames, vector>& chainLocalVarNoParams, vector& chainLabel) { //find function structure FuncInfo* funcI = findFileInfoByName(func, allFuncInfo); set> toProcess; fillToProcess(funcI, toProcess); map processedFrom; for (auto& pairs : toProcess) { FuncInfo* funcTo = pairs.first; FuncInfo* funcFrom = pairs.second; SgFile::switchToFile(funcFrom->fileName); SgStatement* hedrFrom = funcFrom->funcPointer->GetOriginal(); SgStatement* firstExec = getFirstExecStat(hedrFrom); if (!processedFrom.count(funcFrom)) { if (funcFrom->isMain) insertInitNamesOfFiles(numOfFiles, additional, files, journal, firstExec); SgSymbol* timeF = new SgSymbol(FUNCTION_NAME, "omp_get_wtime", SgTypeDouble(), func); // OR dvtime SgStatement* profCallS = new SgAssignStmt(*new SgVarRefExp(profS[0]), *new SgFunctionCallExp(*timeF)); SgStatement* profCallE = new SgAssignStmt(*new SgVarRefExp(profS[1]), *new SgFunctionCallExp(*timeF)); const string funcName = funcFrom->funcName; SgStatement* proc_moduleF = NULL; const string proc_cpModule = "spf_module_" + funcName; createModule(proc_moduleF, proc_cpModule); SgSymbol* proc_mainModuleCpS = proc_moduleF->symbol(); set inFuncParam; processInFuncParam(funcFrom, inFuncParam); map moduleStmts; map moduleParamStmts; set commonVariables; set externVars; processVarBlock(hedrFrom, firstExec, moduleStmts, moduleParamStmts, commonVariables, externVars, funcFrom, inFuncParam); set addedModuleParams; set localVarNoParams; insertStmtToModule(moduleStmts, moduleParamStmts, addedModuleParams, commonVariables, proc_moduleF, localVarNoParams, externVars, funcName.size()); const string namelabelSymb = funcFrom->funcName + "_label"; SgSymbol* procLabelSymb = createLabel(namelabelSymb, proc_moduleF); chainLabel.push_back(namelabelSymb); hedrFrom->insertStmtAfter(*new SgStatement(USE_STMT, NULL, proc_mainModuleCpS), *hedrFrom); SgFile::switchToFile(func->fileName()); SgStatement* useModuleSt = new SgStatement(USE_STMT); useModuleSt->setSymbol(*proc_mainModuleCpS); func->insertStmtAfter(*useModuleSt, *func); SgSymbol* modS = moduleF->symbol(); SgFile::switchToFile(funcFrom->fileName); SgStatement* useSt = new SgStatement(USE_STMT); useSt->setSymbol(*modS); hedrFrom->insertStmtAfter(*useSt, *hedrFrom); SgStatement* loadBlock = createLoadBlock(loadS, funcFrom, iostat, journal, frmt, unit, files, fileIdx, numOfFiles, profS, frmtProf, unitNull, profCallS, profCallE, localVarNoParams, moduleStmts, commonVariables, createdModuleForIO, moduleNames, unitNum, funcI->funcName, chainLocalVarNoParams, false, procLabelSymb); firstExec->insertStmtBefore(*loadBlock, *firstExec->controlParent()); SgStatement* gotoBlock = new SgStatement(IF_NODE); gotoBlock->addComment("! GOTO NEXT PROGRAM UNIT\n"); gotoBlock->setExpression(0, *new SgVarRefExp(loadS[0]) == *new SgValueExp(1)); loadBlock->insertStmtAfter(*gotoBlock, *loadBlock->controlParent()); // insert gotoBlock and save to module processAllCalls(firstExec, funcTo->funcName, funcFrom->funcName, gotoBlock, localVarNoParams, procLabelSymb); makeDeclaration(hedrFrom, { timeF }); } } SgFile::switchToFile(func->fileName()); } static void processModules(SgFile* file, const vector& allFuncInfo) { vector modules; findModulesInFile(file, modules); for (auto& mod : modules) { const string name = mod->symbol()->identifier(); auto pos = name.find("spf_"); if (pos != string::npos && pos == 0) continue; bool hasContains = false; SgStatement* st = mod->lexNext(); while (st != mod->lastNodeOfStmt() && !hasContains) { hasContains = st->variant() == CONTAINS_STMT; st = st->lexNext(); } vector local; map localParams; set addedToList; findLocalData(mod, hasContains ? st : mod->lastNodeOfStmt(), local, localParams, addedToList, allFuncInfo); SgProcHedrStmt* newF = new SgProcHedrStmt(("spf_cp_" + name).c_str()); if (!hasContains) mod->lastNodeOfStmt()->insertStmtBefore(*new SgStatement(CONTAINS_STMT), *mod); mod->lastNodeOfStmt()->insertStmtBefore(*newF, *mod); newF->AddArg("unit_f", *SgTypeInt()); newF->AddArg("type_of_op", *SgTypeInt()); if (local.size()) { SgExpression& unit = SgAssignOp(*new SgKeywordValExp("unit"), *new SgVarRefExp(*newF->parameter(0))); auto dataRead = new SgInputOutputStmt(READ_STAT, unit, *makeExprList(local)); auto dataWrite = new SgInputOutputStmt(WRITE_STAT, unit, *makeExprList(local)); SgIfStmt* ifBlock = new SgIfStmt(*new SgVarRefExp(*newF->parameter(1)) == *new SgValueExp(0), *dataRead, *dataWrite); newF->lastNodeOfStmt()->insertStmtBefore(*ifBlock, *newF); ifBlock->addComment(("!STORE OR LOAD " + to_string(local.size()) + " ITEMS\n").c_str()); } } } void createCheckpoints(SgFile* file, const map& commonBlocks, const map& filesInfo, const vector& allFuncInfo) { map inFileCp; bool inFile = findSpfCpDir(file, inFileCp); if (!inFile) { processModules(file, allFuncInfo); return; } set commonVars; for (auto& common : commonBlocks) for (auto& elem : common.second->getVariables()) if (elem->getType() != CONST) commonVars.insert(elem->getName()); const vector moduleNames = findAllModules(); SgStatement* moduleF = NULL; createModule(moduleF, "spf_module_checkpoint"); SgSymbol* mainModuleCpS = moduleF->symbol(); for (auto& checkps : inFileCp) { const int cpLine = checkps.first; const int every = checkps.second.every; const int numOfFiles = checkps.second.numOfFiles; const int unitNum = checkps.second.unitNum; const string additional = string("_") + to_string(current_file_id) + "_" + to_string(cpLine); const typeEvery type = checkps.second.type; const int numF = file->numberOfFunctions(); SgStatement* func = NULL; SgStatement* point = NULL; for (int z = 0; z < numF; ++z) { func = file->functions(z); point = func->lexNext(); while (point && ((point->fileName() != file->filename()) || (point->lineNumber() < cpLine)) && point != func->lastNodeOfStmt() && point->variant() != CONTAINS_STMT) point = point->lexNext(); //cp place was found if (point != func->lastNodeOfStmt()) break; point = NULL; func = NULL; } checkNull(func, convertFileName(__FILE__).c_str(), __LINE__); checkNull(point, convertFileName(__FILE__).c_str(), __LINE__); bool createdModuleForIO = createForIOs(filesInfo, func); SgStatement* lastDecl = func->lexNext(); while (lastDecl && !isSgExecutableStatement(lastDecl->lexNext())) lastDecl = lastDecl->lexNext(); checkNull(lastDecl, convertFileName(__FILE__).c_str(), __LINE__); SgStatement* firstExec = lastDecl->lexNext(); vector local; map localParams; set addedToList; findLocalData(func, firstExec, local, localParams, addedToList, allFuncInfo); const string funcName = func->symbol()->identifier(); SgStatement* proc_moduleF = NULL; const string proc_cpModule = "spf_module_" + funcName; createModule(proc_moduleF, proc_cpModule); SgSymbol* proc_mainModuleCpS = proc_moduleF->symbol(); FuncInfo* funcI = findFileInfoByName(func, allFuncInfo); set intentInParams; for (int i = 0; i < funcI->funcParams.countOfPars; ++i) if (funcI->funcParams.isArgIn(i) && !funcI->funcParams.isArgOut(i)) intentInParams.insert(funcI->funcParams.identificators[i]); set inFuncParam; processInFuncParam(funcI, inFuncParam); map moduleStmts; map moduleParamStmts; set commonVariables; set externVars; processVarBlock(func, firstExec, moduleStmts, moduleParamStmts, commonVariables, externVars, funcI, inFuncParam); set addedModuleParams; set localVarNoParams; insertStmtToModule(moduleStmts, moduleParamStmts, addedModuleParams, commonVariables, proc_moduleF, localVarNoParams, externVars, funcName.size()); const vector useOfMods = findUseOfModules(func->lexNext(), firstExec); string filesS = "spf_cp_files" + additional; SgSymbol* files = new SgSymbol(VARIABLE_NAME, filesS.c_str(), createArrayCharType(32, numOfFiles + 1), func); SgArrayRefExp* journal = new SgArrayRefExp(*files, *new SgValueExp(numOfFiles + 1)); //give max len, dont insert int maxFileLen = insertInitNamesOfFiles(numOfFiles, additional, files, journal, NULL); vector profS; string profSs = "spf_cp_prof_s" + additional; string profEs = "spf_cp_prof_e" + additional; profS.push_back(new SgSymbol(VARIABLE_NAME, profSs.c_str(), SgTypeFloat(), func)); profS.push_back(new SgSymbol(VARIABLE_NAME, profEs.c_str(), SgTypeFloat(), func)); SgSymbol* timeF = new SgSymbol(FUNCTION_NAME, "omp_get_wtime", SgTypeDouble(), func); // OR dvtime SgStatement* profCallS = new SgAssignStmt(*new SgVarRefExp(profS[0]), *new SgFunctionCallExp(*timeF)); SgStatement* profCallE = new SgAssignStmt(*new SgVarRefExp(profS[1]), *new SgFunctionCallExp(*timeF)); vector loadS; vector initLoadS; string cpLoadS = "spf_cp_load" + additional; loadS.push_back(new SgSymbol(VARIABLE_NAME, cpLoadS.c_str(), SgTypeInt(), func)); initLoadS.push_back(new SgValueExp(1)); string fileNS = "spf_cp_file_n" + additional; loadS.push_back(new SgSymbol(VARIABLE_NAME, fileNS.c_str(), SgTypeInt(), func)); initLoadS.push_back(new SgValueExp(1)); string iostatS = "spf_cp_iostat" + additional; loadS.push_back(new SgSymbol(VARIABLE_NAME, iostatS.c_str(), SgTypeInt(), func)); initLoadS.push_back(NULL); string loadLabelS = "spf_cp_load_label" + additional; loadS.push_back(new SgSymbol(VARIABLE_NAME, loadLabelS.c_str(), SgTypeInt(), func)); initLoadS.push_back(new SgValueExp(0)); SgExpression& unitNull = SgAssignOp(*new SgKeywordValExp("unit"), *new SgKeywordValExp("*")); SgExpression& unit = SgAssignOp(*new SgKeywordValExp("unit"), *new SgValueExp(unitNum)); SgExpression& frmt = SgAssignOp(*new SgKeywordValExp("fmt"), *new SgKeywordValExp("*")); SgExpression& frmtProf = SgAssignOp(*new SgKeywordValExp("fmt"), *new SgValueExp(("(A,A" + to_string(maxFileLen) + ",F4.2,A)").c_str())); SgExpression* labelIdx = new SgVarRefExp(loadS[3]); SgExpression* iostat = new SgVarRefExp(loadS[2]); SgExpression* fileIdx = new SgVarRefExp(loadS[1]); vector> chainLocalVarNoParamsa; SgStatement* loadBlock = createLoadBlock(loadS, funcI, iostat, journal, frmt, unit, files, fileIdx, numOfFiles, profS, frmtProf, unitNull, profCallS, profCallE, localVarNoParams, moduleStmts, commonVariables, createdModuleForIO, moduleNames, unitNum, funcName, chainLocalVarNoParamsa); lastDecl->insertStmtAfter(*loadBlock, *func); if (funcI->isMain) insertInitNamesOfFiles(numOfFiles, additional, files, journal, lastDecl, false); // make all new declarations makeDeclaration(moduleF, loadS, &initLoadS); makeDeclaration(moduleF, profS); makeDeclaration(moduleF, { files }); makeDeclaration(func, { timeF }); func->insertStmtAfter(*new SgStatement(USE_STMT, NULL, mainModuleCpS), *func); func->insertStmtAfter(*new SgStatement(USE_STMT, NULL, proc_mainModuleCpS), *func); //check use map modulesDone; for (auto& elem : moduleNames) modulesDone[elem] = false; //check with ONLY for (auto& use : useOfMods) { const string modName = use->symbol()->identifier(); if (!modulesDone[modName]) { if (use->expr(0)) // has ONLY { SgExpression* ex = use->expr(0); if (ex && ex->variant() == ONLY_NODE) { modulesDone[modName] = true; auto callName = new SgSymbol(VARIABLE_NAME, ("spf_cp_" + modName).c_str()); ex->setLhs(new SgExpression(EXPR_LIST, new SgVarRefExp(callName), ex->lhs())); } } } } //check other for (auto& use : useOfMods) { const string modName = use->symbol()->identifier(); if (!modulesDone[modName]) modulesDone[modName] = true; } for (auto& elem : modulesDone) { if (!elem.second) { auto callName = new SgSymbol(VARIABLE_NAME, ("spf_cp_" + elem.first).c_str()); SgSymbol* modS = new SgSymbol(VARIABLE_NAME, elem.first.c_str()); vector onlyList; onlyList.push_back(new SgVarRefExp(callName)); if (elem.first == "spf_module_ios") for (int z = 0; z < 3; ++z) onlyList.push_back(new SgVarRefExp(new SgSymbol(VARIABLE_NAME, iosNames[z].c_str()))); SgExpression* only = new SgExpression(ONLY_NODE, makeExprList(onlyList), NULL); SgStatement* use = new SgStatement(USE_STMT, NULL, modS, only, NULL, NULL); func->insertStmtAfter(*use, *func); } } vector> chainLocalVarNoParams; vector chainLabel; processFunctionCallChain(func, allFuncInfo, moduleF, loadS, iostat, journal, frmt, unit, files, fileIdx, every, numOfFiles, additional, profS, frmtProf, unitNull, unitNum, createdModuleForIO, moduleNames, chainLocalVarNoParams, chainLabel); SgStatement* storeBlock = createSaveBlock(loadS, funcI, iostat, journal, frmt, unit, files, fileIdx, numOfFiles, profS, frmtProf, unitNull, profCallS, profCallE, localVarNoParams, moduleStmts, commonVariables, createdModuleForIO, moduleNames, unitNum, chainLocalVarNoParams, chainLabel); point->insertStmtBefore(*storeBlock, *point->controlParent()); vector everyS; vector initS; if (type == typeEvery::TIME) { string everySs = "spf_cp_start" + additional; string everyEs = "spf_cp_end" + additional; everyS.push_back(new SgSymbol(VARIABLE_NAME, everySs.c_str(), SgTypeFloat(), func)); everyS.push_back(new SgSymbol(VARIABLE_NAME, everyEs.c_str(), SgTypeFloat(), func)); initS.push_back(NULL); initS.push_back(NULL); SgStatement* call = new SgAssignStmt(*new SgVarRefExp(everyS[0]), *new SgFunctionCallExp(*timeF)); lastDecl->insertStmtAfter(*call, *func); lastDecl->insertStmtAfter(*new SgStatement(DVM_BARRIER_DIR), *func); storeBlock->insertStmtAfter(call->copy(), *storeBlock); storeBlock->insertStmtAfter(*new SgStatement(DVM_BARRIER_DIR), *storeBlock); call = new SgAssignStmt(*new SgVarRefExp(everyS[1]), *new SgFunctionCallExp(*timeF)); storeBlock->insertStmtBefore(*new SgStatement(DVM_BARRIER_DIR), *storeBlock->controlParent()); storeBlock->insertStmtBefore(*call, *storeBlock->controlParent()); call->lexPrev()->addComment("! STORE CHECKPOINT\n"); storeBlock->setExpression(0, *new SgVarRefExp(everyS[1]) - *new SgVarRefExp(everyS[0]) >= *new SgValueExp(every)); } else if (type == typeEvery::ITER) { string everyIs = "spf_cp_interval" + additional; everyS.push_back(new SgSymbol(VARIABLE_NAME, everyIs.c_str(), SgTypeInt(), func)); initS.push_back(new SgValueExp(0)); SgAssignStmt* init = new SgAssignStmt(*new SgVarRefExp(everyS[0]), *new SgValueExp(0)); storeBlock->insertStmtAfter(*init, *storeBlock); SgAssignStmt* inc = new SgAssignStmt(*new SgVarRefExp(everyS[0]), *new SgVarRefExp(everyS[0]) + *new SgValueExp(1)); storeBlock->insertStmtBefore(*inc, *storeBlock->controlParent()); inc->addComment("! STORE CHECKPOINT\n"); storeBlock->setExpression(0, *new SgVarRefExp(everyS[0]) >= *new SgValueExp(every)); } makeDeclaration(moduleF, everyS, &initS); const int labNum = getNextFreeLabel(); auto nextStLab = new SgLabel(labNum); point->setLabel(*nextStLab); SgStatement* gotoBlock = new SgIfStmt(*new SgVarRefExp(loadS[0]) == *new SgValueExp(1)); gotoBlock->addComment("! GOTO CP\n"); gotoBlock->insertStmtAfter(*new SgGotoStmt(*nextStLab), *gotoBlock); SgAssignStmt* init = new SgAssignStmt(*new SgVarRefExp(loadS[0]), *new SgValueExp(0)); gotoBlock->insertStmtAfter(*init, *gotoBlock); loadBlock->insertStmtAfter(*gotoBlock, *loadBlock->controlParent()); checkForToReplace(gotoBlock, point); } processModules(file, allFuncInfo); } static string cuttingType(const string& all_decl_with_init) { auto iter = all_decl_with_init.find("::"); if (iter == string::npos) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return all_decl_with_init.substr(0, iter); } static SgExpression* moveSaveAssignToMod(SgExpression* ex, SgStatement*& saveModule, map& declLists, const string& procName, bool withInit) { if (saveModule == NULL) createModule(saveModule, "spf_module_save_"); if (withInit) { if (ex->variant() != ASSGN_OP) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else { if (ex->variant() != VAR_REF && ex->variant() != ARRAY_REF) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } SgSymbol* copy = (withInit) ? &ex->lhs()->symbol()->copy() : &ex->symbol()->copy(); copy->changeName((string(copy->identifier()) + "_" + procName).c_str()); SgStatement* decl = NULL; if (withInit) { vector inits = { ex->rhs()->copyPtr() }; decl = makeDeclaration(NULL, { ex->lhs()->symbol() }, &inits); } else decl = makeDeclaration(NULL, { ex->symbol() }, NULL); const string typeKey = cuttingType(decl->unparse()); if (withInit) { decl->expr(0)->lhs()->setLhs(withInit ? ex->lhs()->copyPtr() : ex->copyPtr()); decl->expr(0)->lhs()->lhs()->setSymbol(copy); } else decl->expr(0)->lhs()->setSymbol(copy); auto it = declLists.find(typeKey); if (it == declLists.end()) { declLists.insert(it, make_pair(typeKey, decl)); saveModule->insertStmtAfter(*decl, *saveModule); } else it->second->setExpression(0, new SgExpression(EXPR_LIST, decl->expr(0)->lhs(), it->second->expr(0))); return new SgExpression(RENAME_NODE, new SgVarRefExp((withInit) ? ex->lhs()->symbol() : ex->symbol()), new SgVarRefExp(copy)); } void convertSaveToModule(SgFile* file) { int numF = file->numberOfFunctions(); SgStatement* saveModule = NULL; map declLists; for (int ff = 0; ff < numF; ++ff) { vector renames; SgStatement* func = file->functions(ff); string procName = file->functions(ff)->symbol()->identifier(); set toRem; vector dataValues; map dataRenames; set symbolsDone; vector varsToProcess = { VAR_DECL_90 , DIM_STAT }; for (int z = 0; z < 2; ++z) { SgStatement* st = func->lexNext(); while (st && !isSgExecutableStatement(st)) { if (st->variant() == SAVE_DECL) { printf("save in %d %s\n", st->lineNumber(), st->fileName()); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } if (st->variant() == DATA_DECL && z == 0) { if (saveModule == NULL) createModule(saveModule, "spf_module_save_"); SgStatement* copyData = st->copyPtr(); dataValues.push_back((SgValueExp*)copyData->expr(0)); saveModule->lastNodeOfStmt()->insertStmtBefore(*copyData, *saveModule); toRem.insert(st); } if (st->variant() == varsToProcess[z]) { SgExpression* list = st->expr(0); vector newList; bool changed = false; while (list) { if (list->lhs()->variant() == ASSGN_OP) { changed = true; if (symbolsDone.find(list->lhs()->lhs()->symbol()->identifier()) != symbolsDone.end()) { list = list->rhs(); continue; } symbolsDone.insert(list->lhs()->lhs()->symbol()->identifier()); //printf("here %d %s - %s\n", st->lineNumber(), st->fileName(), list->lhs()->unparse()); renames.push_back(moveSaveAssignToMod(list->lhs(), saveModule, declLists, procName, true)); } else { if (list->lhs()->symbol()) { bool isInData = (list->lhs()->symbol()->attributes() & DATA_BIT) != 0; if (isInData) { changed = true; if (symbolsDone.find(list->lhs()->symbol()->identifier()) != symbolsDone.end()) { list = list->rhs(); continue; } symbolsDone.insert(list->lhs()->symbol()->identifier()); renames.push_back(moveSaveAssignToMod(list->lhs(), saveModule, declLists, procName, false)); string left = renames.back()->lhs()->symbol()->identifier(); convertToUpper(left); string right = renames.back()->rhs()->symbol()->identifier(); convertToUpper(right); dataRenames[left] = right; } else newList.push_back(list->lhs()); } else newList.push_back(list->lhs()); } list = list->rhs(); } if (newList.size() && changed) { reverse(newList.begin(), newList.end()); st->setExpression(0, makeExprList(newList)); } else if (newList.size() == 0 && changed) toRem.insert(st); } st = st->lexNext(); } } for (auto& elem : toRem) elem->deleteStmt(); if (renames.size()) { SgSymbol* modS = new SgSymbol(VARIABLE_NAME, saveModule->symbol()->identifier()); SgStatement* use = new SgStatement(USE_STMT, NULL, modS, makeExprList(renames), NULL, NULL); func->insertStmtAfter(*use, *func); for (auto& dataV : dataValues) { char* value = dataV->thellnd->entry.string_val; string dataS(value); convertToUpper(dataS); dataS = preprocDataString(dataS); for (auto& elem : dataRenames) { auto it = dataS.find(elem.first); if (it != string::npos && (dataS[it + elem.first.size()] == ' ' || dataS[it + elem.first.size()] == '/') && (dataS[it - 1] == ',' || dataS[it - 1] == ' ' || dataS[it - 1] == '/')) { dataS = dataS.substr(0, it) + elem.second + dataS.substr(it + elem.first.size()); } } value = (char*)malloc(dataS.size() + 1); value[dataS.size()] = '\0'; memcpy(value, dataS.c_str(), sizeof(char) * dataS.size()); dataV->thellnd->entry.string_val = value; } } } if (saveModule) saveModule->insertStmtAfter(*new SgImplicitStmt(NULL), *saveModule); } static int getUnit(SgExpression* spec) { int unit = -1; while (spec) { if (spec->lhs() && spec->lhs()->variant() == SPEC_PAIR) { if (spec->lhs()->lhs()->variant() == KEYWORD_VAL) { SgKeywordValExp* val = (SgKeywordValExp*)(spec->lhs()->lhs()); if (spec->lhs()->rhs()->variant() == INT_VAL) { if (val->value() == string("unit")) return spec->lhs()->rhs()->valueInteger(); } else if (spec->lhs()->rhs()->variant() == KEYWORD_VAL) { SgKeywordValExp* valR = (SgKeywordValExp*)(spec->lhs()->rhs()); if (val->value() == string("unit") && valR->value() == string("*")) return -2; } } } else if (spec->variant() == INT_VAL) return spec->valueInteger(); spec = spec->rhs(); } return unit; } void preprocessOpenOperators(SgFile* file, map& filesInfo) { int numF = file->numberOfFunctions(); set unrec; for (int ff = 0; ff < numF; ++ff) { SgStatement* func = file->functions(ff); for (SgStatement* st = func->lexNext(); st != func->lastNodeOfStmt(); st = st->lexNext()) { if (st->variant() == OPEN_STAT) { int unit = getUnit(((SgIOControlStmt*)st)->controlSpecList()); if (unit >= 0) filesInfo[unit].placesOpen.push_back(st); else if (unit != -2) unrec.insert(st); } else if (st->variant() == CLOSE_STAT) { int unit = getUnit(((SgIOControlStmt*)st)->controlSpecList()); if (unit >= 0) filesInfo[unit].placesClose.push_back(st); else if (unit != -2) unrec.insert(st); } else if (st->variant() == WRITE_STAT) { int unit = getUnit(((SgInputOutputStmt*)st)->specList()); if (unit >= 0) filesInfo[unit].placesWrite.push_back(st); else if (unit != -2) unrec.insert(st); } else if (st->variant() == READ_STAT) { int unit = getUnit(((SgInputOutputStmt*)st)->specList()); if (unit >= 0) filesInfo[unit].placesRead.push_back(st); else if (unit != -2) unrec.insert(st); } else if (st->variant() == CONTAINS_STMT) break; } } for (auto& elem : unrec) elem->unparsestdout(); /*for (auto& elem : filesInfo) { if (elem.second.placesClose.size() != elem.second.placesOpen.size()) if (elem.second.placesClose.size() > 0 && elem.second.placesOpen.size() > 0) printf("UNIT = %d has not equal open and close\n", elem.first); if (elem.second.placesClose.size() == 0 && elem.second.placesWrite.size() > 0 && elem.second.placesRead.size() == 0) printf("UNIT = %d need to save\n", elem.first); }*/ }