#include "leak_detector.h" #include #include #include #include #include #include #include #include #include "dvm.h" #include "enddo_loop_converter.h" #include "../Utils/errors.h" #include "../Utils/utils.h" #include "../Utils/SgUtils.h" using namespace std; static vector *currMessages; static set allLables; static void copyLabelAndComents(SgStatement *from, SgStatement *to) { if (from->hasLabel()) to->setLabel(*from->label()); if (from->comments()) to->setComments(from->comments()); } static SgLabel* getUniqLabel(unsigned was) { while (1) { was++; if (allLables.find(was) == allLables.end()) break; } SgLabel *ret = new SgLabel(was); return ret; } static vector convertArithIf(SgStatement *curr) { SgExpression *cond = curr->expr(0); SgExpression *lb = curr->expr(1); SgLabel *arith_lab[3]; int i = 0; while (lb) { SgLabel *lab = ((SgLabelRefExp *)(lb->lhs()))->label(); arith_lab[i] = lab; i++; lb = lb->rhs(); } SgStatement *replaceSt; SgType *type = NULL; if (cond->type()) type = cond->type(); else type = SgTypeInt(); auto condS = new SgSymbol(VARIABLE_NAME, ("ar_If_C" + std::to_string(curr->lineNumber())).c_str(), type, curr->getScopeForDeclare()); SgStatement *assignCond = new SgAssignStmt(*new SgVarRefExp(*condS), *cond); vector toAdd = { condS }; makeDeclaration(curr, toAdd); if (arith_lab[1]->getLabNumber() == arith_lab[2]->getLabNumber()) replaceSt = new SgIfStmt(*new SgVarRefExp(*condS) < *new SgValueExp(0), *new SgGotoStmt(*arith_lab[0]), *new SgGotoStmt(*arith_lab[1])); else replaceSt = new SgIfStmt(*new SgVarRefExp(*condS) < *new SgValueExp(0), *new SgGotoStmt(*arith_lab[0]), *new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(0), *new SgGotoStmt(*arith_lab[1]), *new SgGotoStmt(*arith_lab[2]))); return { assignCond, replaceSt }; } static vector convertComGoto(SgStatement *curr) { SgExpression *cond = curr->expr(1); SgExpression *lb = curr->expr(0); vector labs; while (lb) { labs.push_back(((SgLabelRefExp *)(lb->lhs()))->label()); lb = lb->rhs(); } SgStatement *replace = NULL; auto condS = new SgSymbol(VARIABLE_NAME, ("com_Goto_C" + std::to_string(curr->lineNumber())).c_str(), SgTypeInt(), curr->getScopeForDeclare()); SgStatement *assignCond = new SgAssignStmt(*new SgVarRefExp(*condS), *cond); vector toAdd = { condS }; makeDeclaration(curr, toAdd); if (labs.size() == 1) replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(1), *new SgGotoStmt(*labs[0])); else replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp((int)labs.size()), *new SgGotoStmt(*labs.back())); for (int z = (int)labs.size() - 2; z >= 0; --z) replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(z + 1), *new SgGotoStmt(*labs[z]), *replace); return { assignCond, replace }; } static pair convertForall(SgStatement *st) { if (st->variant() != FORALL_NODE && st->variant() != FORALL_STAT) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgForStmt *ret = NULL; SgExpression *ex = st->expr(0); SgExpression *cond = st->expr(1); vector>> loops; SgSymbol* construct = NULL; if (BIF_LL3(st->thebif)) construct = SymbMapping(NODE_SYMB(BIF_LL3(st->thebif))); while (ex) { if (ex->lhs()->variant() != FORALL_OP) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgExpression *left = ex->lhs(); if (left->lhs()->lhs()->variant() == DDOT) loops.push_back(make_pair(left->symbol(), make_tuple(left->lhs()->lhs()->lhs(), left->lhs()->lhs()->rhs(), left->lhs()->rhs()))); else loops.push_back(make_pair(left->symbol(), make_tuple(left->lhs()->lhs(), left->lhs()->rhs(), (SgExpression*)NULL))); ex = ex->rhs(); } SgStatement *insertPoint = NULL; for (int z = loops.size() - 1; z >= 0; --z) { if (z == loops.size() - 1) { SgIfStmt *condIf = cond == NULL ? NULL : new SgIfStmt(*cond); ret = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), condIf); if (condIf) insertPoint = condIf; else insertPoint = ret; } else ret = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), ret); } if (construct) ret->setConstructName(construct); return make_pair(ret, insertPoint); } template funcConv(SgStatement*)> static void convert(SgStatement *&curr, const wstring &messageE, const wstring &messageR) { const int lineNum = curr->lineNumber(); vector replaceSt = funcConv(curr); if (curr->controlParent()->variant() == LOGIF_NODE) LogIftoIfThen(curr->controlParent()); for (int k = (int)replaceSt.size() - 1; k >= 0; --k) curr->insertStmtAfter(*(replaceSt[k]), *curr->controlParent()); copyLabelAndComents(curr, curr->lexNext()); SgStatement *toDel = curr; curr = curr->lexNext(); toDel->deleteStmt(); //TODO //char buf[512]; //sprintf(buf, (to_string(messageE) + " on line %d\n").c_str(), lineNum); //addToGlobalBufferAndPrint(buf); currMessages->push_back(Messages(NOTE, lineNum, messageR, messageE, 2002)); } static void tryToCorrectLoop(SgForStmt *&forSt, map &endOfLoops) { SgLabel *tmp = endOfLoops[forSt]; SgStatement *curr = forSt->lexNext(); SgStatement *lastNode; // find the last node of this FOR with label while (curr) { if (curr->hasLabel()) if (curr->label() == tmp) break; curr = curr->lexNext(); } lastNode = curr; // replace last node with CONTINUE with NEW label and replace all FOR labels to new label lastNode->insertStmtAfter(*new SgContinueStmt(), *(curr->controlParent())); SgStatement *next = lastNode->lexNext(); SgLabel *newLab = getUniqLabel(curr->label()->getLabNumber()); next->setLabel(*newLab); lastNode = next; curr = forSt; while (curr != lastNode) { if (curr->variant() == FOR_NODE || curr->variant() == WHILE_NODE) { SgLabel *currLab = ((SgForStmt*)curr)->endOfLoop(); if (currLab) if (currLab->getLabNumber() == tmp->getLabNumber()) BIF_LABEL_USE(curr->thebif) = newLab->thelabel; } curr = curr->lexNext(); } curr = forSt->lexNext(); // convert all arithmetic if and computed goto to simple if with goto //TODO: add ASSIGN GOTO while (curr != lastNode) { wstring bufR = L""; if (curr->variant() == ARITHIF_NODE) { convert(curr, L"convert arithmetic IF to simple IF", R96); continue; } else if (curr->variant() == COMGOTO_NODE) { convert(curr, L"convert computed GOTO to simple IF", R97); continue; } else if (curr->variant() == ASSGOTO_NODE) { SgExpression *lb = curr->expr(0); SgSymbol *assignedS = curr->symbol(); //TODO } curr = curr->lexNext(); } } static void tryToConverLoop(SgForStmt *&forSt, map &endOfLoops) { const int lineNum = forSt->lineNumber(); if (forSt->isEnddoLoop() == false) { int result = forSt->convertLoop(); if (result == 0) { tryToCorrectLoop(forSt, endOfLoops); result = forSt->convertLoop(); if (result == 0) { char buf[512]; sprintf(buf, "ERROR: can not convert to END DO loop on line %d\n", lineNum); addToGlobalBufferAndPrint(buf); currMessages->push_back(Messages(ERROR, lineNum, R98, L"can not convert to END DO loop", 2003)); } } if (result > 0) { char buf[512]; sprintf(buf, "convert to END DO loop on line %d\n", lineNum); addToGlobalBufferAndPrint(buf); currMessages->push_back(Messages(NOTE, lineNum, R99 , L"convert to END DO loop", 2004)); } } } static void getAllLabels(SgFile *file) { allLables.clear(); int funcNum = file->numberOfFunctions(); for (int i = 0; i < funcNum; ++i) { SgStatement *st = file->functions(i); SgStatement *lastNode = st->lastNodeOfStmt(); while (st && st != lastNode) { if (st->hasLabel()) { SgLabel *lab = st->label(); if (lab) allLables.insert(lab->getLabNumber()); } st = st->lexNext(); } } } static void fillEndOfLoop(SgStatement *st, map &endOfLoops, map &toProcessLoops) { SgStatement *lastNode = st->lastNodeOfStmt(); while (st && st != lastNode) { if (st->variant() == CONTAINS_STMT) break; if (st->variant() == FOR_NODE) { SgForStmt *forSt = (SgForStmt*)st; if (forSt->isEnddoLoop() == false) { SgLabel *endOfLoop = forSt->endOfLoop(); if (endOfLoop != NULL) { endOfLoops[forSt] = endOfLoop; auto it = toProcessLoops.find(endOfLoop->getLabNumber()); if (it == toProcessLoops.end()) toProcessLoops.insert(it, make_pair(endOfLoop->getLabNumber(), forSt)); } else __spf_print(1, " Can not find end of labeled loop on line %d\n", forSt->lineNumber()); } } st = st->lexNext(); } } void ConverToEndDo(SgFile *file, vector &messagesForFile) { currMessages = &messagesForFile; getAllLabels(file); const int funcNum = file->numberOfFunctions(); for (int i = 0; i < funcNum; ++i) { SgStatement *st = file->functions(i); SgStatement *lastNode = st->lastNodeOfStmt(); vector parentLoops; map endOfLoops; map toProcessLoops; fillEndOfLoop(st, endOfLoops, toProcessLoops); for (auto &loop : toProcessLoops) tryToConverLoop(loop.second, endOfLoops); // convert FORALL bool repeat = true; while (repeat) { repeat = false; vector toDel; st = file->functions(i); while (st != lastNode) { if (st->variant() == CONTAINS_STMT) break; if (st->variant() == FORALL_STAT || st->variant() == FORALL_NODE) { pair newSt = convertForall(st); checkNull(newSt.first, convertFileName(__FILE__).c_str(), __LINE__); st->insertStmtBefore(*newSt.first, *st->controlParent()); copyLabelAndComents(st, newSt.first); //copy for END copyLabelAndComents(st->lastNodeOfStmt(), newSt.first->lastNodeOfStmt()); SgStatement *start = st->lexNext(); SgStatement *end = st->lastNodeOfStmt(); for (; start != end; ) { SgStatement *copy = start->copyPtr(); if (copy->variant() == FORALL_STAT || copy->variant() == FORALL_NODE) repeat = true; newSt.second->lastNodeOfStmt()->insertStmtBefore(*copy, *newSt.second); copyLabelAndComents(start, copy); if (start->variant() != IF_NODE) { start = start->lastNodeOfStmt(); start = start->lexNext(); } else { while (start->variant() != CONTROL_END) start = start->lastNodeOfStmt(); start = start->lexNext(); } } if (st->variant() == FORALL_STAT) { SgStatement *copy = st->lexNext()->copyPtr(); newSt.second->lastNodeOfStmt()->insertStmtBefore(*copy, *newSt.second); copyLabelAndComents(start, copy); } toDel.push_back(st); } st = st->lexNext(); } for (auto &elem : toDel) elem->deleteStmt(); } } } //return vector createIfConditions(stack &conds, stack &ifBlocks, SgStatement *control) { vector ifSt = { NULL, NULL }; const int id = control->getFileId(); SgProject* proj = control->getProject(); const int line = control->lineNumber(); auto scope = getFuncStat(control); vector toDecls; while (!conds.empty()) { SgSymbol* s = NULL; if (control->variant() == SWITCH_NODE) { auto nextN = checkSymbNameAndCorrect(string("spf_sc_C" + std::to_string(ifBlocks.top()->lineNumber()))); s = new SgSymbol(VARIABLE_NAME, nextN.c_str(), control->expr(0)->type(), scope); } else { auto nextN = checkSymbNameAndCorrect(string("spf_if_C" + std::to_string(ifBlocks.top()->lineNumber()))); s = new SgSymbol(VARIABLE_NAME, nextN.c_str(), SgTypeBool(), scope); } toDecls.push_back(s); SgAssignStmt* check = new SgAssignStmt(*new SgVarRefExp(s), *conds.top()); check->setFileId(id); check->setProject(proj); check->setlineNumber(line); if (ifSt[0]) { if (ifSt[1]) { ifSt[1] = new SgIfStmt(*new SgExpression(NOT_OP, new SgVarRefExp(s)), *ifSt[1]); ifSt[1]->insertStmtAfter(*ifSt[0], *ifSt[1]); } else ifSt[1] = new SgIfStmt(*new SgExpression(NOT_OP, new SgVarRefExp(s)), *ifSt[0]); ifSt[1]->setFileId(id); ifSt[1]->setProject(proj); ifSt[1]->setlineNumber(line); ifSt[0] = check; } else ifSt[0] = check; ifBlocks.top()->setExpression(0, *new SgVarRefExp(s)); ifBlocks.pop(); conds.pop(); } makeDeclaration(scope, toDecls); return ifSt; }