#include "../Utils/leak_detector.h" #include #include #include #include "ParRegions_func.h" #include "expand_extract_reg.h" using std::map; using std::pair; using std::vector; using std::string; using std::to_string; using std::make_pair; static inline void insertParRegDir(SgStatement *start, const string ®Name) { // !SPF PARALLEL_REG regName SgStatement *regSt = new SgStatement(SPF_PARALLEL_REG_DIR); checkNull(start->getFile(), convertFileName(__FILE__).c_str(), __LINE__); SgSymbol *regSymb = findSymbolOrCreate(start->getFile(), regName.c_str()); regSt->setSymbol(*regSymb); start->insertStmtBefore(*regSt, *start->controlParent()); } static inline void insertEndParReg(SgStatement *end) { // !SPF END PARALLEL_REG SgStatement *regSt = new SgStatement(SPF_END_PARALLEL_REG_DIR); SgStatement *next = end->lexNext(); checkNull(next, convertFileName(__FILE__).c_str(), __LINE__); next->insertStmtBefore(*regSt, *next->controlParent()); } static inline void insertParRegDirs(SgStatement *start, SgStatement *end, const string ®Name) { insertParRegDir(start, regName); insertEndParReg(end); } static bool checkIfLineIsImplicit(const ParallelRegion *reg, const string &fileName, const int line) { if (reg && reg->GetName() != "DEFAULT") { auto regLines = reg->GetLinesByLine(fileName, line); if (regLines && regLines->isImplicit()) return true; // error } return false; } static bool hasOwnControlParent(SgStatement *start, SgStatement *end) { if (start == end) return true; if (!end->controlParent()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return (end->variant() != CONTROL_END && start->controlParent() == end->controlParent() || end->variant() == CONTROL_END && start->controlParent() == end->controlParent()->controlParent()); } static bool isNotComposit(SgStatement *st) { if (!st) return true; return (st->lastNodeOfStmt() == st); } bool expandExtractReg(const string &fileName, int startLine, int endLine, const vector ®ions, vector &messagesForFile, const bool toDelete) { bool error = false; if (SgFile::switchToFile(fileName) != -1) { SgStatement *begin = SgStatement::getStatementByFileAndLine(fileName, startLine); SgStatement *end = SgStatement::getStatementByFileAndLine(fileName, endLine); int lastLine = -1; for (auto st = current_file->firstStatement(); st; st = st->lexNext()) lastLine = st->lineNumber(); for (; !begin && startLine <= lastLine;) begin = SgStatement::getStatementByFileAndLine(fileName, ++startLine); for (; !end && endLine > 0;) end = SgStatement::getStatementByFileAndLine(fileName, --endLine); // check user lines // 2. запрещено располагать N1 и N2 в неисполняемых операторах int errorLine; bool localError = false; if (!(isSgExecutableStatement(end) || end->variant() == ENTRY_STAT)) { localError = true; errorLine = endLine; } if (!(isSgExecutableStatement(begin) || begin->variant() == ENTRY_STAT)) { localError = true; errorLine = startLine; } if (localError) { __spf_print(1, "bad directive position on line %d: it can be placed only after all DATA statements\n", errorLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad directive position: it can be placed only after all DATA statements"); __spf_printToLongBuf(bufwR, R12); messagesForFile.push_back(Messages(ERROR, errorLine, bufwR, bufwE, 1001)); error = true; } // 1. N1 <= N2 if (startLine > endLine) { __spf_print(1, "bad lines position: end line %d must be greater or equel begin line %d\n", endLine, startLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: end line %d must be greater or equel begin line %d", endLine, startLine); __spf_printToLongBuf(bufwR, R13); messagesForFile.push_back(Messages(ERROR, endLine, bufwR, bufwE, 1001)); error = true; } // 2. запрещено располагать N1 и N2 во фрагментах разных ОР и неявных строках auto beginReg = getRegionByLine(regions, fileName, startLine); auto endReg = getRegionByLine(regions, fileName, endLine); if (!toDelete && beginReg && endReg && beginReg != endReg) { __spf_print(1, "bad lines position: begin and end lines can not be placed at differect regions\n"); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: begin and end lines can not be placed at differect regions"); __spf_printToLongBuf(bufwR, R14); messagesForFile.push_back(Messages(ERROR, endLine, bufwR, bufwE, 1001)); error = true; } localError = false; if (checkIfLineIsImplicit(endReg, fileName, endLine)) { localError = true; errorLine = endLine; } if (checkIfLineIsImplicit(beginReg, fileName, startLine)) { localError = true; errorLine = startLine; } if (localError) { __spf_print(1, "bad lines position on line %d: begin and end lines can not be placed at region implicit lines\n", errorLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: begin and end lines can not be placed at region implicit lines"); __spf_printToLongBuf(bufwR, R15); messagesForFile.push_back(Messages(ERROR, errorLine, bufwR, bufwE, 1001)); error = true; } // X. запрещено выбирать строки в разных функциях SgStatement *beginFunc = begin, *endFunc = end; while (!isSgProgHedrStmt(beginFunc)) beginFunc = beginFunc->controlParent(); while (!isSgProgHedrStmt(endFunc)) endFunc = endFunc->controlParent(); if (beginFunc != endFunc) { __spf_print(1, "bad lines position: begin and end lines can not be placed at different functions\n"); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: begin and end lines can not be placed at different functions"); __spf_printToLongBuf(bufwR, R16); messagesForFile.push_back(Messages(ERROR, errorLine, bufwR, bufwE, 1001)); error = true; } // 3. при добавлении запрещено содержать внутри отрезка [N1,N2] фрагменты разных ОР const ParallelRegionLines *beginLines = NULL, *endLines = NULL; map> internalLines; for (auto ® : regions) { auto regLines = reg->GetLines(fileName); for (auto &lines : *regLines) { if (!lines.isImplicit()) { /* if (startLine >= lines.lines.first && startLine <= lines.lines.second) beginLines = &lines; if (endLine >= lines.lines.first && endLine <= lines.lines.second) endLines = &lines; */ if (startLine < lines.lines.first && endLine > lines.lines.second) { auto it = internalLines.find(reg); if (it == internalLines.end()) it = internalLines.insert(it, make_pair(reg, vector())); it->second.push_back(&lines); } } } } if (!toDelete && internalLines.size() > 1) { __spf_print(1, "bad lines position on line %d: begin and end lines can not include fragments of different regions at extending operation\n", startLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: begin and end lines can not include fragments of different regions at extending operation"); __spf_printToLongBuf(bufwR, R17); messagesForFile.push_back(Messages(ERROR, startLine, bufwR, bufwE, 1001)); error = true; } // use cases if (beginReg && beginReg->GetName() != "DEFAULT") beginLines = beginReg->GetLinesByLine(fileName, startLine); if (endReg && endReg->GetName() != "DEFAULT") endLines = endReg->GetLinesByLine(fileName, endLine); // delete all internal fragments for (auto ®Lines : internalLines) { for (auto &lines : regLines.second) { lines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); lines->stats.second->GetOriginal()->lexNext()->deleteStmt(); } } if (error) return true; localError = false; if (beginLines && !endLines) { if (!toDelete) { if (hasOwnControlParent(beginLines->stats.first->GetOriginal(), end)) { insertEndParReg(end); beginLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); } else { errorLine = endLine; localError = true; } } else { if (hasOwnControlParent(beginLines->stats.first->GetOriginal(), begin) && begin->variant() != CONTROL_END) { if (startLine == beginLines->lines.first) beginLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); else insertEndParReg(begin->lexPrev()); beginLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); } else { errorLine = startLine; localError = true; } } } else if (endLines && !beginLines) { if (!toDelete) { if (hasOwnControlParent(begin, endLines->stats.first->GetOriginal())) { insertParRegDir(begin, endReg->GetName()); endLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); } else { errorLine = startLine; localError = true; } } else { if (hasOwnControlParent(endLines->stats.first->GetOriginal(), end) && isNotComposit(end)) { if (endLine == endLines->lines.second) endLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); else insertParRegDir(end->lexNext(), endReg->GetName()); endLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); } else { errorLine = endLine; localError = true; } } } else if (!beginLines && !endLines) { if (!toDelete) { string regName; // TODO: create correct new region name if (internalLines.size()) regName = internalLines.begin()->first->GetName(); else regName = "reg" + to_string(regions.size()); if (hasOwnControlParent(begin, end)) insertParRegDirs(begin, end, regName); else { __spf_print(1, "bad lines %d-%d position: expected lines with the same scope for creating region fragment\n", startLine, endLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: expected lines with the same scope for creating region fragment"); __spf_printToLongBuf(bufwR, R18); messagesForFile.push_back(Messages(ERROR, endLine, bufwR, bufwE, 1001)); error = true; } } } else if (beginLines && endLines) { if (!toDelete) { if (beginLines != endLines && hasOwnControlParent(beginLines->stats.first->GetOriginal(), endLines->stats.first->GetOriginal())) { beginLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); endLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); } else { __spf_print(1, "bad lines %d-%d position: can not extend region fragments with different scope\n", startLine, endLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines %d-%d position: can not extend region fragments with different scope", startLine, endLine); __spf_printToLongBuf(bufwR, R19, startLine, endLine); messagesForFile.push_back(Messages(ERROR, endLine, bufwR, bufwE, 1001)); error = true; } } else { int errorLine1, errorLine2; localError = false; /* if (beginLines == endLines && !hasOwnControlParent(begin, end)) { localError = true; errorLine = startLine; errorLine1 = startLine; errorLine2 = endLine; } */ if (hasOwnControlParent(beginLines->stats.first->GetOriginal(), begin) && begin->variant() != CONTROL_END) { if (startLine == beginLines->lines.first) beginLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); else insertEndParReg(begin->lexPrev()); } else { localError = true; errorLine = startLine; errorLine1 = beginLines->lines.first; errorLine2 = startLine; } if (hasOwnControlParent(endLines->stats.first->GetOriginal(), end) && isNotComposit(end)) { if (endLine == endLines->lines.second) endLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); else insertParRegDir(end->lexNext(), endReg->GetName()); } else { localError = true; errorLine = endLine; errorLine1 = endLine; errorLine2 = endLines->lines.second; } if (beginLines != endLines) { beginLines->stats.second->GetOriginal()->lexNext()->deleteStmt(); endLines->stats.first->GetOriginal()->lexPrev()->deleteStmt(); } /* if (localError) { __spf_print(1, "bad lines %d-%d position: expected line with the same scope for extracting region fragment\n", errorLine1, errorLine2); std::wstring bufw; __spf_printToLongBuf(bufw, L"bad lines position: expected line with the same scope for extracting region fragment"); messagesForFile.push_back(Messages(ERROR, errorLine, bufw, 1001)); error = true; } */ } } if (localError) { __spf_print(1, "bad lines position: expected lines with the same control parent on line %d\n", errorLine); std::wstring bufwE, bufwR; __spf_printToLongBuf(bufwE, L"bad lines position: expected lines with the same control parent"); __spf_printToLongBuf(bufwR, R20); messagesForFile.push_back(Messages(ERROR, errorLine, bufwR, bufwE, 1001)); error = true; } // TODO: check: delete all possible empty fragments /* SgStatement *parStart = NULL; SgStatement *parEnd = NULL; while (begin->variant() != PROG_HEDR && begin->variant() != PROC_HEDR && begin->variant() != FUNC_HEDR) begin = begin->controlParent(); end = begin->lastNodeOfStmt(); for (auto st = begin; st != end; st = st->lexNext()) { if (st->variant() == SPF_PARALLEL_REG_DIR) parStart = st; if (st->variant() == SPF_END_PARALLEL_REG_DIR) { parEnd = st; if (parStart && parStart->lexNext() == parEnd) { parStart->deleteStmt(); parEnd->deleteStmt(); parStart = NULL; parEnd = NULL; } } } */ } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return error; }