#include "fix_common_blocks.h" using std::vector; using std::map; using std::set; using std::string; using std::to_string; using std::pair; using std::make_pair; using std::stack; using std::deque; using std::reverse; using std::tuple; //// main function --> fixCommonBlocks ////// step1: build union for each common block /// main function: // renew unions for all common blocks in the file static void BuildNewCommDecls(SgFile* file, const map allCommonBlocks, map>& newCommonDecls, map>>& commDecls, set& badCommon, map>& notUsedVars, vector& programUnits); // get names of variables and array elements, which were referenced in programm unit static set getUses(SgStatement* firstSt, const set& commonVarNames); static void getUsesFromExpr(SgExpression* expr, const set& commonVarNames, set& used); // splits arrays into elements and replaces not used vars with empty constraints static bool splitType(deque& d, bool check_use, const set& namesOfUsedVars); // create constraits set static deque makeConstraints(deque& constraints, const set& namesOfUsedVars, set& notUsedVars); // build union static bool buildConstraintsUnion(deque& U, deque B, const set& namesOfUsedVars, pair& problemConstraints); static bool docheckUnequalConstraints(deque& U, deque& B, deque& newU, pair& problemConstraints); static bool check(deque& A, deque& B, pair& problemConstraints); /// small help functions: static string getParentName(const string& name); static bool equalDims(const CommConstraint& a, const CommConstraint& b); static bool equalConstraints(const CommConstraint& a, const CommConstraint& b); static void addElem(deque& comm, const CommConstraint& elem); ////// // change names of variables in 'constraints' static void fixNames(deque& constraints, const string& commName); ////// step2: transformation /// main function // peform transformation on every program unit in the file static void fixFunctions(SgFile* file, vector programUnits, map>& newCommonDecls, map>>& commDecls, const set& badCommon, map>& notUsedVars); // get pairs of names (namesOldToNew) for renaming static bool getNamesOldToNew(deque newDecl, deque oldDecl, map& namesOldToNew); // create new symbols for new variables in new common declaration (constraints) static void makeCommVarSymbs(const deque& constraints, SgFile* file, SgStatement* func, string commName, map& symbs, vector& needNewDecl); // delete from program unit all references to names in commVarNames static void deleteOldVars(SgStatement* firstSt, const set& commVarNames); // calls fixExpression for each statement, replaces names in data statement static void renameVariables(SgStatement* firstSt, const map& newVarSymbs, const map& namesOldToNew); // replacing variables or array elements in expression expr if their names are in namesOldToNew static SgExpression* fixExpression(SgExpression* expr, const map& newSymbs, const map& namesOldToNew); // make new exprList exprssion for new declaration decl with symbols from newSymbs static SgExpression* makeExprListForCommon(const deque& decl, const map& newSymbs, SgFile* file, SgStatement* firstSt); // replace old common declarations with new ones static void rewriteCommon(SgStatement* firstSt, map& commListExprs); /// help functions: static SgExpression* makeIdxFromStr(const string& str); // make new expression of array element static SgExpression* newArrElemExpr(const string& newName, const map& newSymbs); static bool variablePositionComp(const Variable* lhs, const Variable* rhs); ////// CommConstraint::CommConstraint(const Variable* var, bool u, const string& funcName, const string& fileName) { used = u; for (const auto& use : var->getAllUse()) { if (use.getFunctionName() == funcName) { SgSymbol* symb = use.getUseS(); identifier = symb->identifier(); DeclInfo dInfo = DeclInfo(identifier, fileName, use.getDeclaratedPlace()->lineNumber()); uses.push_back(dInfo); if ((symb->attributes() & DATA_BIT) != 0) used = true; type = symb->type(); typeVariant = type->variant(); vector decls; declaratedInStmt(symb, &decls, false); Distribution::Array* arr = NULL; for (auto decl : decls) { arr = getArrayFromDeclarated(decl, identifier); // TODO: for arrays located in the same place in common, with the same names, the same structure will be given, // even if they have DIFFERENT dimensions (should be different structures) if (arr != NULL) break; } if (arr != NULL) { arrayInfo = arr; size = arr->GetTypeSize(); for (auto x : arr->GetSizes()) size *= x.second - x.first + 1; SgArrayType* arrType = isSgArrayType(type); if (arrType != NULL) typeVariant = arrType->baseType()->variant(); else __spf_print(1, "! array with no array type!\n"); } else size = getSizeOfType(type); } } } CommConstraint::CommConstraint(const string& name, SgType* t, bool u) : used(u), type(t), identifier(name) { typeVariant = type->variant(); size = getSizeOfType(type); } CommConstraint::CommConstraint(const string& name, SgType* t, bool u, vector& us) : used(u), type(t), identifier(name), uses(us) { typeVariant = type->variant(); size = getSizeOfType(type); } string getParentName(const string& name) { size_t len = name.find("%"); size_t posB = name.find("("); if (len == string::npos) if (posB == string::npos) return name; else len = posB; else if (posB != string::npos && posB < len) len = posB; return name.substr(0, len); } void getUsesFromExpr(SgExpression* expr, const set& commonVarNames, set& used) { if (expr == NULL) return; if (expr->variant() == VAR_REF || expr->variant() == ARRAY_REF) { string name = expr->symbol()->identifier(); if (commonVarNames.find(getParentName(name)) != commonVarNames.end()) { if (expr->variant() == VAR_REF) used.insert(name); else if (expr->variant() == ARRAY_REF) { SgArrayRefExp* arrExpr = (SgArrayRefExp*)expr; if (arrExpr->lhs() == NULL) used.insert(name); else // it's array element { SgExpression* exprList = arrExpr->lhs(); bool ok = true; int x; while (exprList != NULL && ok) // TODO: evaluate indexes of elements if they are written using loop variable { if (-1 == CalculateInteger(exprList->lhs(), x)) ok = false; exprList = exprList->rhs(); } if (ok) used.insert(expr->sunparse()); else used.insert(name); } } } } getUsesFromExpr(expr->lhs(), commonVarNames, used); getUsesFromExpr(expr->rhs(), commonVarNames, used); } set getUses(SgStatement* firstSt, const set& commonVarNames) { set used; SgStatement* lastSt = firstSt->lastNodeOfStmt(); for (SgStatement* curSt = firstSt; curSt != lastSt; curSt = curSt->lexNext()) { int var = curSt->variant(); if (var != COMM_STAT && var != VAR_DECL && var != VAR_DECL_90 && var != DIM_STAT) // { for (int i = 0; i < 3; i++) if (curSt->expr(i) != NULL) getUsesFromExpr(curSt->expr(i), commonVarNames, used); } } return used; } bool equalDims(const CommConstraint& a, const CommConstraint& b) { const vector>& adim = a.arrayInfo->GetSizes(); const vector>& bdim = b.arrayInfo->GetSizes(); if (adim.size() != bdim.size()) return false; for (int i = 0; i < adim.size(); i++) { if (adim[i].second - adim[i].first != bdim[i].second - bdim[i].first) return false; } } // TODO: add attributes to CommConstraints, check if a and b have equal attributes bool equalConstraints(const CommConstraint& a, const CommConstraint& b) { if ((a.arrayInfo != NULL && b.arrayInfo == NULL) || ((a.arrayInfo == NULL && b.arrayInfo != NULL))) return false; if (a.typeVariant != b.typeVariant || a.size != b.size) return false; if (a.arrayInfo != NULL) return a.arrayInfo->GetTypeSize() == b.arrayInfo->GetTypeSize() && equalDims(a, b); return true; } void addElem(deque& comm, const CommConstraint& elem) { if (elem.typeVariant == 0 && !comm.empty() && comm.back().typeVariant == 0) comm.back().size += elem.size; else comm.push_back(elem); } // TODO: check attributes: do not split arrays with pointer or target attributes if check_use == true bool splitType(deque& d, bool check_use, const set& namesOfUsedVars = {}) { CommConstraint var = d.front(); string name = var.identifier; if (var.typeVariant == 0 || (check_use && var.used)) return false; if (var.arrayInfo != NULL) // TODO: arrays can be split not only into individual elements, but also into smaller arrays { d.pop_front(); const auto dims = var.arrayInfo->GetSizes(); int numOfDims = dims.size(); SgType* elemType = new SgType(var.typeVariant); int elemNum = var.size / var.arrayInfo->GetTypeSize(); for (int k = elemNum - 1; k >= 0; k--) { string newName = name + "("; int ind = k; for (int i = 0; i < numOfDims; i++) { auto d = dims[i]; int dimLen = d.second - d.first + 1; newName += to_string(ind % dimLen + d.first); if (i < numOfDims - 1) newName += ","; ind = ind / dimLen; } newName += ")"; CommConstraint newVar = CommConstraint(newName, elemType, var.used, var.uses); if (check_use && !newVar.used && namesOfUsedVars.find(newName) != namesOfUsedVars.end()) newVar.used = true; d.push_front(newVar); } return true; } else { if (check_use && (var.used == false)) { d.pop_front(); CommConstraint newVar = CommConstraint(var.identifier, var.size); d.push_front(newVar); return true; } else return false; } } deque makeConstraints(deque& constraints, const set& namesOfUsedVars, set& notUsedVars) { deque res; while (!constraints.empty()) { string curName = constraints.front().identifier; if (!splitType(constraints, true, namesOfUsedVars)) { addElem(res, constraints.front()); constraints.pop_front(); } else notUsedVars.insert(curName); } return res; } bool check(deque& A, deque& B, pair& problemConstraints) { while (!A.empty() && !B.empty()) { if (B.front().size > A.front().size) { if (!splitType(B, false)) { problemConstraints.second = A.front(); return false; } } else if (B.front().size < A.front().size) { if (A.front().typeVariant == 0) { A.front().size -= B.front().size; B.pop_front(); } else { problemConstraints.second = A.front(); return false; } } else { if (A.front().typeVariant != 0 && B.front().typeVariant != 0 && !equalConstraints(A.front(), B.front())) { problemConstraints.second = A.front(); return false; } B.pop_front(); A.pop_front(); } } return true; } bool docheckUnequalConstraints(deque& U, deque& B, deque& newU, pair& problemConstraints) { if (U.front().typeVariant == 0) { addElem(newU, B.front()); U.front().size -= B.front().size; B.pop_front(); } else { deque temp; temp.push_front(U.front()); if (!check(B, temp, problemConstraints)) { problemConstraints.first = U.front(); return false; } addElem(newU, U.front()); U.pop_front(); } return true; } bool buildConstraintsUnion(deque& U, deque B, const set& namesOfUsedVars, pair& problemConstraints) { deque newU; while (!U.empty() && !B.empty()) { if (U.front().size < B.front().size) { if (!docheckUnequalConstraints(B, U, newU, problemConstraints)) return false; } else if (U.front().size > B.front().size) { if (!docheckUnequalConstraints(U, B, newU, problemConstraints)) return false; } else { if (U.front().typeVariant == 0 || B.front().typeVariant == 0 || equalConstraints(U.front(), B.front())) { if (U.front().typeVariant == 0) addElem(newU, B.front()); else if (B.front().typeVariant == 0) addElem(newU, U.front()); else { U.front().uses.insert(U.front().uses.end(), B.front().uses.begin(), B.front().uses.end()); // adding to funcs addElem(newU, U.front()); } U.pop_front(); B.pop_front(); } else { problemConstraints = make_pair(B.front(), U.front()); return false; } } } while (!B.empty()) { addElem(newU, B.front()); B.pop_front(); } while (!U.empty()) { addElem(newU, U.front()); U.pop_front(); } if (!newU.empty() && newU.back().typeVariant == 0) newU.pop_back(); U = newU; return true; } bool getNamesOldToNew(deque newDecl, deque oldDecl, map& namesOldToNew) { bool needChange = false; map rename; while (!oldDecl.empty() && !newDecl.empty()) { if (newDecl.front().typeVariant == 0) // => oldDecl.front().typeVariant == 0 { if (oldDecl.front().size > newDecl.front().size) { oldDecl.front().size -= newDecl.front().size; needChange = true; } else oldDecl.pop_front(); newDecl.pop_front(); } else if (newDecl.front().size > oldDecl.front().size) { needChange = true; deque tmp; tmp.push_front(newDecl.front()); splitType(tmp, false); while (!tmp.empty() && !oldDecl.empty()) { if (oldDecl.front().typeVariant == 0) { if (oldDecl.front().size > tmp.front().size) oldDecl.front().size -= tmp.front().size; else oldDecl.pop_front(); } else { rename[oldDecl.front().identifier] = tmp.front().identifier; oldDecl.pop_front(); } tmp.pop_front(); } newDecl.pop_front(); } else if (oldDecl.front().size > newDecl.front().size) // => oldDecl.front().typeVariant == 0 { needChange = true; oldDecl.front().size -= newDecl.front().size; newDecl.pop_front(); } else // == and newDecl.front().typeVariant != 0 { if (oldDecl.front().typeVariant == 0) needChange = true; else { if (oldDecl.front().identifier.find('(') != string::npos) { needChange = true; rename[oldDecl.front().identifier] = newDecl.front().identifier; } else rename[oldDecl.front().identifier] = newDecl.front().identifier; } oldDecl.pop_front(); newDecl.pop_front(); } } if (!oldDecl.empty() || !newDecl.empty()) needChange = true; if (needChange) namesOldToNew.insert(rename.begin(), rename.end()); return needChange; } void makeCommVarSymbs(const deque& constraints, SgFile* file, SgStatement* func, string commName, map& symbs, vector& needNewDecl) { for (const CommConstraint& var : constraints) { if (var.typeVariant != 0) { SgSymbol* symb = findSymbolOrCreate(file, var.identifier, var.type->copyPtr(), func); symbs[var.identifier] = symb; needNewDecl.push_back(symb); } } } void deleteOldVars(SgStatement* firstSt, const set& commVarNames) { SgStatement* lastSt = firstSt->lastNodeOfStmt(); vector stmtsToDelete; for (SgStatement* curSt = firstSt; curSt != lastSt; curSt = curSt->lexNext()) { if (curSt->variant() == VAR_DECL || curSt->variant() == VAR_DECL_90) { SgVarDeclStmt* varDeclSt = (SgVarDeclStmt*)curSt; vector varsToDelete; for (int i = 0; i < varDeclSt->numberOfVars(); i++) { SgExpression* var = varDeclSt->var(i); string varName = ""; if (var->variant() == ASSGN_OP) varName = var->lhs()->symbol()->identifier(); else varName = var->symbol()->identifier(); if (commVarNames.find(varName) != commVarNames.end()) varsToDelete.push_back(var); } if (varDeclSt->numberOfVars() == varsToDelete.size()) stmtsToDelete.push_back(curSt); else for (SgExpression* var : varsToDelete) varDeclSt->deleteTheVar(*var); } else if (curSt->variant() == DIM_STAT) { SgExpression* ex = curSt->expr(0); bool first = true; vector leftExprs; while (ex != NULL) { string name = ex->lhs()->symbol()->identifier(); if (commVarNames.find(name) == commVarNames.end()) leftExprs.push_back(ex->lhs()); ex = ex->rhs(); } if (leftExprs.empty()) stmtsToDelete.push_back(curSt); else curSt->setExpression(0, makeExprList(leftExprs)); } // TODO: delete common variables form attributes statements (like DIM_STAT) } for (SgStatement* st : stmtsToDelete) st->deleteStmt(); } SgExpression* makeIdxFromStr(const string& str) { vector items; int num = 0; for (char c : str) { if ('0' <= c && c <= '9') num = num * 10 + (c - '0'); else if (c == ',' || c == ')') { SgExpression* ex = new SgValueExp(num); items.push_back(ex); num = 0; } } reverse(items.begin(), items.end()); SgExpression* exprList = makeExprList(items, false); return exprList; } SgExpression* newArrElemExpr(const string& newName, const map& newSymbs) { size_t pos = newName.find('('); SgExpression* newExpr = new SgArrayRefExp(*newSymbs.at(newName.substr(0, pos))); newExpr->setLhs(makeIdxFromStr(newName.substr(pos))); return newExpr; } SgExpression* fixExpression(SgExpression* expr, const map& newSymbs, const map& namesOldToNew) { if (expr == NULL) return NULL; if (expr->variant() == VAR_REF || expr->variant() == ARRAY_REF) { string name = expr->symbol()->identifier(); auto nameIt = namesOldToNew.find(name); if (nameIt != namesOldToNew.end()) { string newName = nameIt->second; auto symbIt = newSymbs.find(newName); if (symbIt == newSymbs.end()) // variable -> array element return newArrElemExpr(newName, newSymbs); else // variable -> variable or array name -> array name { SgSymbol* newSymb = symbIt->second; expr->setSymbol(newSymb); } } else { string fullName = expr->sunparse(); auto fullNameIt = namesOldToNew.find(fullName); if (fullNameIt != namesOldToNew.end()) { string newName = fullNameIt->second; auto symbIt = newSymbs.find(newName); if (symbIt == newSymbs.end()) // array element -> array element return newArrElemExpr(newName, newSymbs); else // array element -> variable { SgVariableSymb* varSymb = (SgVariableSymb*)symbIt->second; SgExpression* newExpr = new SgVarRefExp(*varSymb); return newExpr; } } } } SgExpression* lhs = fixExpression(expr->lhs(), newSymbs, namesOldToNew); if (lhs != NULL) expr->setLhs(lhs); SgExpression* rhs = fixExpression(expr->rhs(), newSymbs, namesOldToNew); if (rhs != NULL) expr->setRhs(rhs); return NULL; } void renameVariables(SgStatement* firstSt, const map& newVarSymbs, const map& namesOldToNew) { SgStatement* lastSt = firstSt->lastNodeOfStmt(); for (SgStatement* curSt = firstSt; curSt != NULL && curSt != lastSt; curSt = curSt->lexNext()) { if (curSt->variant() == DATA_DECL) { SgValueExp* dataExpr = (SgValueExp*)curSt->expr(0); map data = splitData({ dataExpr }); string newDataStr = "data "; bool needChange = false; int left = data.size(); for (pair& item : data) { auto nameIt = namesOldToNew.find(item.first); if (nameIt != namesOldToNew.end()) { newDataStr += nameIt->second + "/" + item.second + "/"; needChange = true; } else newDataStr += item.first + "/" + item.second + "/"; left--; if (left != 0) newDataStr += ", "; } if (needChange) { SgExpression* es = new SgExpression(STMT_STR); char* value = (char*)malloc(newDataStr.size() + 1); value[newDataStr.size()] = '\0'; memcpy(value, newDataStr.c_str(), sizeof(char) * newDataStr.size()); es->thellnd->entry.string_val = value; curSt->setExpression(0, es); } } else if (isSgExecutableStatement(curSt) || curSt->variant() == EQUI_STAT) { for (int i = 0; i < 3; i++) { SgExpression* expr = fixExpression(curSt->expr(i), newVarSymbs, namesOldToNew); if (expr != NULL) curSt->setExpression(i, expr); } } } } SgExpression* makeExprListForCommon(const deque& decl, const map& newSymbs, SgFile* file, SgStatement* firstSt) { vector items; for (auto it = decl.rbegin(); it != decl.rend(); it++) { if (it->typeVariant == 0) continue; SgSymbol* symb = NULL; bool old = false; auto symbIt = newSymbs.find(it->identifier); if (symbIt != newSymbs.end()) symb = symbIt->second; else { symb = findSymbolOrCreate(file, it->identifier, it->type, firstSt); old = true; } SgVariableSymb* varSymb = isSgVariableSymb(symb); if (varSymb->type()->variant() == T_ARRAY) { SgExpression* newExpr = new SgArrayRefExp(*varSymb); items.push_back(newExpr); } else { SgExpression* newExpr = new SgVarRefExp(symb); items.push_back(newExpr); } } SgExpression* exprList = makeExprList(items, false); return exprList; } void rewriteCommon(SgStatement* firstSt, map& commListExprs) { vector commonStmtsToDelete; for (SgStatement* st = firstSt; st != firstSt->lastDeclaration()->lexNext(); st = st->lexNext()) { if (st->variant() == COMM_STAT) { SgExpression* ex = st->expr(0); bool first = true; SgExpression* prev = NULL; while (ex != NULL) { string commName = ""; SgSymbol* s = ex->symbol(); if (s == NULL) commName = "spf_unnamed"; else commName = s->identifier(); auto commIt = commListExprs.find(commName); if (commIt != commListExprs.end()) { if (commIt->second != NULL) { ex->setLhs(commIt->second); commIt->second = NULL; if (first) first = false; prev = ex; ex = ex->rhs(); } else { if (first) { st->setExpression(0, ex->rhs()); ex = st->expr(0); } else { prev->setRhs(ex->rhs()); ex = prev->rhs(); } } } else ex = ex->rhs(); } if (st->expr(0) == NULL) commonStmtsToDelete.push_back(st); } } for (SgStatement* st : commonStmtsToDelete) st->deleteStmt(); } void fixNames(deque& constraints, const string& commName) { for (auto& var : constraints) { for (char& c : var.identifier) { if (c == ')' || c == '(') c = 'l'; if (c == ',') c = '_'; } var.identifier = commName + "_" + var.identifier; } } bool variablePositionComp(const Variable* lhs, const Variable* rhs) { return lhs->getPosition() < rhs->getPosition(); } void fixFunctions(SgFile* file, vector programUnits, map>& newCommonDecls, map>>& commDecls, const set& badCommon, map>& notUsedVars) { for (SgStatement* unitSt : programUnits) { string funcName = unitSt->symbol()->identifier(); if (commDecls.find(funcName) == commDecls.end()) continue; SgStatement* firstSt = unitSt; map commListExprs; map newVarSymbs; // new symbols for new variables map namesOldToNew; // for ranaming: old name -> new name vector needNewDecl; for (auto& common : commDecls[funcName]) { string commName = common.first; if (badCommon.find(commName) != badCommon.end()) continue; const deque& newDecl = newCommonDecls.at(commName); vector varsNeedNewSymb; bool needChange = getNamesOldToNew(newDecl, common.second, namesOldToNew); if (!needChange) continue; makeCommVarSymbs(newDecl, file, firstSt, commName, newVarSymbs, needNewDecl); commListExprs[commName] = makeExprListForCommon(newDecl, newVarSymbs, file, firstSt); } if (!commListExprs.empty()) { for (const auto& item : commListExprs) for (const auto& x : commDecls[funcName][item.first]) notUsedVars[funcName].insert(x.identifier); deleteOldVars(unitSt, notUsedVars[funcName]); renameVariables(unitSt, newVarSymbs, namesOldToNew); makeDeclaration(needNewDecl, unitSt); rewriteCommon(firstSt, commListExprs); } } } void BuildNewCommDecls(SgFile* file, const map allCommonBlocks, map>& newCommonDecls, map>>& commDecls, set& badCommon, map>& notUsedVars, vector& programUnits) { string fileName = file->filename(); SgStatement* curSt = file->firstStatement(); while (curSt != NULL) { if (curSt->variant() == PROG_HEDR || curSt->variant() == PROC_HEDR || curSt->variant() == FUNC_HEDR || curSt->variant() == BLOCK_DATA || curSt->variant() == MODULE_STMT) { programUnits.push_back(curSt); string funcName = curSt->symbol()->identifier(); for (auto item : allCommonBlocks) { string commName = item.first; if (badCommon.find(commName) != badCommon.end()) continue; CommonBlock* commonBlock = item.second; vector vars = commonBlock->getVariables(fileName, funcName); if (vars.size() == 0) continue; sort(vars.begin(), vars.end(), variablePositionComp); set varNames; for (const Variable* var : vars) varNames.insert(var->getName()); set namesOfUsedVars = getUses(curSt, varNames); bool hasChar = false; bool hasNotChar = false; deque constraints; for (const Variable* var : vars) { CommConstraint newConstr = CommConstraint(var, false, funcName, fileName); if (newConstr.typeVariant == T_STRING || newConstr.typeVariant == T_ARRAY) // ignore common blocks with strings hasChar = true; else hasNotChar = true; if (namesOfUsedVars.find(newConstr.identifier) != namesOfUsedVars.end()) newConstr.used = true; constraints.push_back(newConstr); } if (hasChar && hasNotChar) // TDOO: make proper warning message or separate such common blocks __spf_print(1, "common block '%s' ('%s':%d) contains variables of symbolic and numeric types. It is required to divide\n", commName.c_str(), fileName.c_str(), constraints.back().uses.back().lineNum); if (hasChar) { badCommon.insert(commName); continue; } deque curComm = makeConstraints(constraints, namesOfUsedVars, notUsedVars[funcName]); commDecls[funcName][commName] = curComm; bool res; pair problemConstraints; res = buildConstraintsUnion(newCommonDecls[commName], curComm, namesOfUsedVars, problemConstraints); if (!res) { badCommon.insert(commName); for (auto x : problemConstraints.first.uses) // TODO: make proper warning message for (auto y : problemConstraints.second.uses) __spf_print(1, "variables '%s' and '%s' in one storage association (common block '%s') have different types (files - %s:%d and %s:%d)\n", x.varName.c_str(), y.varName.c_str(), commName.c_str(), x.fileName.c_str(), x.lineNum, y.fileName.c_str(), y.lineNum); } } curSt = curSt->lastNodeOfStmt(); } else curSt = curSt->lexNext(); } } // main function void fixCommonBlocks(const map> allFuncInfo, const map allCommonBlocks, SgProject* project) // TODO: separate into 2 steps? { int filesNum = project->numberOfFiles(); map>>> commDecls; // file_name -> function_name -> common block name -> old declaration of common block map> newCommonDecls; // name of common block -> cur builded declaration map> notUsedVars; map> programUnitsInFile; set badCommon; for (int i = 0; i < filesNum; i++) // first step { SgFile* file = &project->file(i); string fileName = file->filename(); file->switchToFile(fileName); BuildNewCommDecls(file, allCommonBlocks, newCommonDecls, commDecls[fileName], badCommon, notUsedVars, programUnitsInFile[fileName]); } for (auto& elem : newCommonDecls) fixNames(elem.second, elem.first); for (int i = 0; i < filesNum; i++) // second step { SgFile* file = &project->file(i); string fileName = file->filename(); file->switchToFile(fileName); fixFunctions(file, programUnitsInFile[fileName], newCommonDecls, commDecls[fileName], badCommon, notUsedVars); } }