#include "../Utils/leak_detector.h" #include #include #include #include #include "../Utils/SgUtils.h" #include "../Utils/CommonBlock.h" #include "../GraphCall/graph_calls.h" #include "../ExpressionTransform/expr_transform.h" #include "dvm.h" #include "IR.h" #include "CFGraph.h" using namespace std; using namespace SAPFOR; static map>> dictArgs; static map> dictArgsByArg; static int lastNumReg = 0; int Argument::lastNumArg = 0; int Instruction::lastNumInstr = 0; static SAPFOR::Argument* processExpression(SgExpression* ex, vector& blocks, const FuncInfo* func, const vector>& commonVars, SAPFOR::Argument *isLeft = NULL); static SAPFOR::Argument* createRegister() { const string newName = "_reg" + to_string(lastNumReg++); auto it = dictArgs.find(newName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(newName, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::REG, CFG_MEM_TYPE::LOCAL_, newName), make_pair("reg", (SgSymbol*)NULL)))); else if (it->second.first->getType() != CFG_ARG_TYPE::REG) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } string getNameByArg(SAPFOR::Argument* arg) { auto it = dictArgsByArg.find(arg); if (it != dictArgsByArg.end()) return it->second.first; return ""; } SgSymbol* getSybolByArg(SAPFOR::Argument* arg) { auto it = dictArgsByArg.find(arg); if (it != dictArgsByArg.end()) return it->second.second; return NULL; } string createName(const vector>& commonVars, const FuncInfo* func, SgSymbol* s, SgStatement* scope, CFG_MEM_TYPE& mType) { SgSymbol* resultName = NULL; auto isFunc = isSgFuncHedrStmt(func->funcPointer->GetOriginal()); if (isFunc) resultName = isFunc->resultName(); string newName = "_"; SgSymbol* var = OriginalSymbol(s); checkNull(var, convertFileName(__FILE__).c_str(), __LINE__); bool inCommon = false; if (commonVars.size() && var == s) { const string name = s->identifier(); for (auto& var : commonVars) { if (var.first->getName() == name) { const int pos = var.first->getPosition(); auto groupedByPos = var.second->getGroupedVars(); if (groupedByPos.count(pos) == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); string firstSynonim = groupedByPos[pos][0]->getName(); newName += var.second->getName() + string("%") + firstSynonim; inCommon = true; mType = CFG_MEM_TYPE::COMMON_; break; } } } if (!inCommon) { if (s->variant() == FUNCTION_NAME || (var == resultName && resultName)) { newName += func->funcName; mType = CFG_MEM_TYPE::FUNC_RES_; } else if (s->variant() == PROCEDURE_NAME) { newName += var->identifier(); mType = CFG_MEM_TYPE::LOCAL_; } else if (s->variant() == FIELD_NAME) { newName += var->identifier(); mType = CFG_MEM_TYPE::FILED_; } else { auto prog = isSgProgHedrStmt(scope); if (prog) { const string varName = var->identifier(); for (int z = 0; z < func->funcParams.identificators.size(); ++z) { if (func->funcParams.identificators[z] == varName) { newName += prog->nameWithContains() + string("%") + var->identifier() + "%" + to_string(z); mType = CFG_MEM_TYPE::FUNC_PARAM_; break; } } if (newName == "_") // not inited { newName += prog->nameWithContains() + string("%") + var->identifier(); mType = CFG_MEM_TYPE::LOCAL_; } } else { newName += scope->symbol()->identifier() + string("%") + var->identifier(); mType = CFG_MEM_TYPE::MODULE_; } } } return newName; } SAPFOR::Argument* createArg(const string& fullName, const string& name, CFG_MEM_TYPE mType) { auto it = dictArgs.find(fullName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(fullName, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::VAR, mType, fullName), make_pair(name, (SgSymbol*)NULL)))); else if (it->second.first->getType() != CFG_ARG_TYPE::VAR && it->second.first->getMemType() != mType) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } static SAPFOR::Argument* createArg(SgSymbol* var, const vector>& commonVars, const FuncInfo* func) { SgStatement* where = OriginalSymbol(var)->scope(); if (!where) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); CFG_MEM_TYPE mType(CFG_MEM_TYPE::NONE_); const string newName = createName(commonVars, func, var, where, mType); auto it = dictArgs.find(newName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(newName, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::VAR, mType, newName), make_pair(var->identifier(), var)))); else if (it->second.first->getType() != CFG_ARG_TYPE::VAR && it->second.first->getMemType() != mType) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } static SAPFOR::Argument* createConstArg(SgExpression* exp) { string newName = "---"; auto value = isSgValueExp(exp); int var = exp->variant(); CFG_ARG_TYPE type = CFG_ARG_TYPE::CONST; if (var == INT_VAL) newName = to_string(value->intValue()); else if (var == FLOAT_VAL) newName = value->floatValue(); else if (var == DOUBLE_VAL) newName = value->doubleValue(); else if (var == CHAR_VAL) newName = value->charValue(); else if (var == COMPLEX_VAL) { const string real = value->realValue()->unparse(); const string im = value->imaginaryValue()->unparse(); newName = real + "%" + im; } else if (var == BOOL_VAL) newName = value->boolValue() ? "TRUE" : "FALSE"; else if (var == KEYWORD_VAL) newName = string("%") + "key_arg_" + isSgKeywordValExp(exp)->value(); else if (var == CONSTRUCTOR_REF) { type = CFG_ARG_TYPE::CONSTR_REF; newName = string("%") + "constructor_ref_" + to_string(SgStatement::getCurrProcessLine()) + "_" + string(exp->unparse()); } else if (var == STRING_VAL) { type = CFG_ARG_TYPE::CONST_STR; newName = string("%") + value->stringValue(); } else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto it = dictArgs.find(newName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(newName, make_pair(new SAPFOR::Argument(type, CFG_MEM_TYPE::LOCAL_, type == CFG_ARG_TYPE::CONSTR_REF ? exp->unparse() : newName), make_pair("const", (SgSymbol*)NULL)))); else if (it->second.first->getType() != type) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } static SAPFOR::Argument* createArrayArg(SgExpression* array_ref, vector& blocks, const FuncInfo* func, int& numArgs, const vector>& commonVars) { auto ref = isSgArrayRefExp(array_ref); if (ref == NULL) { if (array_ref->variant() == STRING_VAL) return createConstArg(array_ref); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } SgSymbol* var = ref->symbol(); SgStatement* where = OriginalSymbol(var)->scope(); if (!where) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); vector> args; SAPFOR::Argument* empty = NULL; numArgs = ref->numberOfSubscripts(); for (int z = 0; z < numArgs; ++z) { auto arg = ref->subscript(z); if (arg->variant() != DDOT) args.push_back(make_tuple(arg->variant(), processExpression(arg, blocks, func, commonVars), empty, empty)); else { SAPFOR::Argument *left = NULL, *right = NULL, *step = NULL; bool fullRange = false; if (arg->lhs()) { if (arg->lhs()->variant() == DDOT) { fullRange = true; if (arg->lhs()->lhs()) left = processExpression(arg->lhs()->lhs(), blocks, func, commonVars); if (arg->lhs()->rhs()) right = processExpression(arg->lhs()->rhs(), blocks, func, commonVars); } else left = processExpression(arg->lhs(), blocks, func, commonVars); } if (arg->rhs()) { if (fullRange) step = processExpression(arg->rhs(), blocks, func, commonVars); else right = processExpression(arg->rhs(), blocks, func, commonVars); } args.push_back(make_tuple(DDOT, left, right, step)); } } for (auto& arg : args) { Instruction* instr = NULL; if (get<0>(arg) != DDOT) instr = new Instruction(CFG_OP::REF, get<1>(arg)); else instr = new Instruction(CFG_OP::RANGE, get<1>(arg), get<2>(arg), get<3>(arg)); blocks.push_back(new IR_Block(instr)); } CFG_MEM_TYPE mType(CFG_MEM_TYPE::NONE_); const string newName = createName(commonVars, func, var, where, mType); auto it = dictArgs.find(newName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(newName, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::ARRAY, mType, newName), make_pair(var->identifier(), var)))); else if (it->second.first->getType() != CFG_ARG_TYPE::ARRAY && it->second.first->getMemType() != mType) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } static SAPFOR::Argument* createRefArg(SgExpression* exp) { //TODO: assign true type! string newName = exp->unparse(); CFG_ARG_TYPE type = CFG_ARG_TYPE::RECORD; auto it = dictArgs.find(newName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(newName, make_pair(new SAPFOR::Argument(type, CFG_MEM_TYPE::LOCAL_, newName), make_pair("ref", (SgSymbol*)NULL)))); else if (it->second.first->getType() != type) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } static SAPFOR::Argument* createConstArg(int value) { string s = to_string(value); auto itS = dictArgs.find(s); if (itS == dictArgs.end()) itS = dictArgs.insert(itS, make_pair(s, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::CONST, CFG_MEM_TYPE::LOCAL_, s), make_pair("const", (SgSymbol*)NULL)))); else if (itS->second.first->getType() != CFG_ARG_TYPE::CONST) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return itS->second.first; } static SAPFOR::Argument* getFuncArg(const string& fName) { auto it = dictArgs.find(fName); if (it == dictArgs.end()) it = dictArgs.insert(it, make_pair(fName, make_pair(new SAPFOR::Argument(CFG_ARG_TYPE::FUNC, fName), make_pair(fName, (SgSymbol*)NULL)))); else if (it->second.first->getType() != CFG_ARG_TYPE::FUNC) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return it->second.first; } template static bool processArgs(funcStatement* call, int num, vector& blocks, const FuncInfo* func, const vector>& commonVars, vector* labels = NULL) { bool hasLabelArg = false; vector args; for (int z = 0; z < num; ++z) { if (call->arg(z)->variant() == LABEL_ARG) { hasLabelArg = true; auto labRef = isSgLabelRefExp(call->arg(z)->lhs()); if (labRef == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); args.push_back(createConstArg(labRef->label()->getLabNumber())); if (labels) labels->push_back(labRef->label()->getLabNumber()); } else args.push_back(processExpression(call->arg(z), blocks, func, commonVars)); } for (auto& arg : args) { Instruction* instr = new Instruction(CFG_OP::PARAM, arg); blocks.push_back(new IR_Block(instr)); } return hasLabelArg; } static SAPFOR::Argument* processExpression(SgExpression* ex, vector& blocks, const FuncInfo* func, const vector>& commonVars, SAPFOR::Argument* isLeft) { static map typeMap = { { ADD_OP, CFG_OP::ADD }, { MULT_OP, CFG_OP::MULT }, { SUBT_OP, CFG_OP::SUBT }, { DIV_OP, CFG_OP::DIV }, { UNARY_ADD_OP, CFG_OP::UN_ADD }, { MINUS_OP, CFG_OP::UN_MINUS }, { GT_OP, CFG_OP::GT }, { GE_OP, CFG_OP::GE }, { GTEQL_OP, CFG_OP::GE }, { LT_OP, CFG_OP::LT }, { LE_OP, CFG_OP::LE }, { LTEQL_OP, CFG_OP::LE }, { OR_OP, CFG_OP::OR }, { AND_OP, CFG_OP::AND }, { EQ_OP, CFG_OP::EQ }, { EQV_OP, CFG_OP::EQV }, { NEQV_OP, CFG_OP::NEQV }, { NOTEQL_OP, CFG_OP::NEQV }, { NOT_OP, CFG_OP::NOT }, { FUNC_CALL, CFG_OP::F_CALL }, { EXP_OP, CFG_OP::POW }, { CONCAT_OP, CFG_OP::CONCAT } }; if (ex) { const int var = ex->variant(); if ((var == VAR_REF || var == CONST_REF || var == LABEL_REF) && !ex->lhs() && !ex->rhs()) // обращение к переменной { if (var == CONST_REF) { SgExpression* value = CalculateInteger(ex->copyPtr()); if (isSgValueExp(value)) return createConstArg(value); else return createArg(ex->symbol(), commonVars, func); } else if (var == LABEL_REF) { auto labRef = isSgLabelRefExp(ex); if (labRef == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return createConstArg(labRef->label()->getLabNumber()); } else return createArg(ex->symbol(), commonVars, func); } else if (isSgValueExp(ex)) return createConstArg(ex); else if (var == ADD_OP || var == MULT_OP || var == SUBT_OP || var == DIV_OP || var == GT_OP || var == GE_OP || var == LT_OP || var == LE_OP || var == OR_OP || var == AND_OP || var == EQ_OP || var == EQV_OP || var == NEQV_OP || var == EXP_OP || var == NOTEQL_OP || var == LTEQL_OP || var == GTEQL_OP || var == CONCAT_OP) { auto arg1 = processExpression(ex->lhs(), blocks, func, commonVars); auto arg2 = processExpression(ex->rhs(), blocks, func, commonVars); auto reg = createRegister(); Instruction* instr = new Instruction(typeMap[var], arg1, arg2, reg); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == MINUS_OP || var == UNARY_ADD_OP || var == NOT_OP) { auto arg1 = processExpression(ex->lhs(), blocks, func, commonVars); auto reg = createRegister(); Instruction* instr = new Instruction(typeMap[var], arg1, NULL, reg); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == ARRAY_REF) { int numArgs = 0; auto arg1 = createArrayArg(ex, blocks, func, numArgs, commonVars); if (numArgs == 0) return arg1; auto reg = isLeft ? NULL : createRegister(); Instruction* instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(numArgs), isLeft ? isLeft : reg); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == ARRAY_OP) // A([L] : [R] [:[Step]]) { SgExpression* ref = ex->lhs(); SAPFOR::Argument* arrayRef = NULL; if (ref->lhs() || ref->rhs()) arrayRef = processExpression(ref, blocks, func, commonVars); SgExpression* range = ex->rhs(); if (range->variant() != DDOT) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); bool hasStep = range->lhs()->variant() == DDOT; SAPFOR::Argument *step = NULL, *left = NULL, *right = NULL; if (hasStep) { step = processExpression(range->rhs(), blocks, func, commonVars); range = range->lhs(); } if (range->lhs()) left = processExpression(range->lhs(), blocks, func, commonVars); if (range->rhs()) right = processExpression(range->rhs(), blocks, func, commonVars); Instruction* instr = new Instruction(CFG_OP::RANGE, left, right, step); blocks.push_back(new IR_Block(instr)); int numArgs = 0; auto arg1 = arrayRef ? arrayRef : createArrayArg(ref, blocks, func, numArgs, commonVars); auto reg = isLeft ? NULL : createRegister(); instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(1), isLeft ? isLeft : reg); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == FUNC_CALL) { auto fCall = isSgFunctionCallExp(ex); bool hasLabelArgs = processArgs(fCall, fCall->numberOfArgs(), blocks, func, commonVars); if (hasLabelArgs) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); string callName = "_ERROR_"; for (int z = 0; z < func->callsFromDetailed.size() && callName == "_ERROR_"; ++z) if (func->callsFromDetailed[z].pointerDetailCallsFrom.first == ex) callName = func->callsFromDetailed[z].detailCallsFrom.first; SAPFOR::Argument* fArg = getFuncArg(callName); auto reg = createRegister(); Instruction* instr = new Instruction(typeMap[var], fArg, createConstArg(fCall->numberOfArgs()), reg, NULL, ex); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == KEYWORD_ARG) { auto keyW = isSgKeywordArgExp(ex); if (!keyW->lhs() || !keyW->rhs()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (keyW->lhs()->variant() != KEYWORD_VAL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto reg = createRegister(); Instruction* instr = NULL; auto kewVal = isSgKeywordValExp(keyW->lhs()); if (kewVal->value() == string("kind") || kewVal->value() == string("len")) instr = new Instruction(CFG_OP::CAST, processExpression(keyW->value(), blocks, func, commonVars), createConstArg(keyW->lhs()), reg); else instr = new Instruction(CFG_OP::ASSIGN, processExpression(keyW->value(), blocks, func, commonVars), createConstArg(keyW->lhs()), reg); blocks.push_back(new IR_Block(instr)); return reg; } else if (var == RECORD_REF) { auto reg = isLeft ? NULL : createRegister(); Instruction* instr = new Instruction(isLeft ? CFG_OP::REC_REF_STORE : CFG_OP::REC_REF_LOAD, createRefArg(ex), NULL, isLeft ? isLeft : reg); blocks.push_back(new IR_Block(instr)); return reg; //TODO: need to add more detalization vector listOfRecods; SgExpression* curr = ex; while (curr->variant() == RECORD_REF) { listOfRecods.push_back(curr->rhs()); curr = curr->lhs(); } listOfRecods.push_back(curr); std::reverse(listOfRecods.begin(), listOfRecods.end()); //recExpressionPrint(ex); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SAPFOR::Argument* returnReg = NULL; for (int z = 0; z < listOfRecods.size(); z++) { auto& elem = listOfRecods[z]; bool isLast = (listOfRecods.size() - 1) == z; SAPFOR::Argument* arg = NULL; if (elem->variant() == ARRAY_REF && elem->lhs()) { auto copy = elem->copyPtr(); SgExpression* left = copy->lhs(); copy->setLhs(NULL); arg = processExpression(copy, blocks, func, commonVars, isLeft); auto reg = createRegister(); if (returnReg == NULL) { printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else { Instruction* instr = new Instruction(CFG_OP::REC_REF, returnReg, arg, reg); blocks.push_back(new IR_Block(instr)); } returnReg = reg; if (isLast) { copy->setLhs(left); processExpression(copy, blocks, func, commonVars, isLeft); auto lastType = blocks.back()->getInstruction()->getOperation(); if (lastType != CFG_OP::STORE && lastType != CFG_OP::LOAD) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); blocks.back()->getInstruction()->setArg1(reg); arg = NULL; } } else arg = processExpression(elem, blocks, func, commonVars, isLeft); auto reg = createRegister(); if (arg) { if (returnReg == NULL) { Instruction* instr = new Instruction(CFG_OP::LOAD, arg, NULL, reg); blocks.push_back(new IR_Block(instr)); } else { Instruction* instr = new Instruction(CFG_OP::REC_REF, returnReg, arg, reg); blocks.push_back(new IR_Block(instr)); } } returnReg = reg; // return last } return returnReg; } else if (var == CONSTRUCTOR_REF) return createConstArg(ex); else if (var == SPEC_PAIR) return processExpression(ex->rhs(), blocks, func, commonVars); else { __spf_print(1, "unknown expression '%s'\n", tag[ex->variant()]); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } } printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return NULL; } static SgStatement* processLabel(SgStatement* st, const int firstInstr, const vector& blocks, map& labels) { const int var = st->variant(); if (var == FORMAT_STAT) return st; if (st->label()) { int lab = st->label()->getLabNumber(); if (labels.count(lab) == 0) labels[lab] = blocks[firstInstr]->getInstruction(); } return st; } static SgStatement* getNearestDo(SgStatement* st, SgSymbol* named) { while (st) { int var = st->variant(); if (var == FOR_NODE || var == WHILE_NODE) { if (var == FOR_NODE) { SgSymbol* symb = isSgForStmt(st)->constructName(); if (!named || !symb) break; else if (symb->identifier() == string(named->identifier())) break; } else break; } st = st->controlParent(); if (st == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } return st; } static void findCycleExit(int start, int end, int type, const vector& blocks, SgStatement* curr, int jumpTo) { for (int z = start; z < end; ++z) { if (blocks[z]->getInstruction()->getOperation() == CFG_OP::JUMP) if (blocks[z]->getInstruction()->getOperator()) if (blocks[z]->getInstruction()->getOperator()->variant() == type) { SgSymbol* named = NULL; if (type == CYCLE_STMT) named = isSgCycleStmt(blocks[z]->getInstruction()->getOperator())->constructName(); else if (type == EXIT_STMT) named = isSgExitStmt(blocks[z]->getInstruction()->getOperator())->constructName(); if (getNearestDo(blocks[z]->getInstruction()->getOperator(), named) == curr) blocks[z]->getInstruction()->setArg1(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jumpTo))); } } } static void findReturn(int start, int end, const vector& blocks, int jumpTo) { for (int z = start; z < end; ++z) { if (blocks[z]->getInstruction()->getOperation() == CFG_OP::JUMP) if (blocks[z]->getInstruction()->getOperator()) if (blocks[z]->getInstruction()->getOperator()->variant() == RETURN_STAT) blocks[z]->getInstruction()->setArg1(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jumpTo))); } } static void addGotoTo(int labNum, vector& blocks, SgStatement* st = NULL) { auto arg1 = new SAPFOR::Argument(CFG_ARG_TYPE::LAB, CFG_MEM_TYPE::NONE_, to_string(labNum)); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, arg1, NULL, NULL, st))); } static int getInstructionNumAfterIfJump(int currBlockSize, int shiftBlockNumbers, int countAfterIfInstr) { return currBlockSize + 1 + countAfterIfInstr + shiftBlockNumbers; } static void createCompoundGoto(int num, SgExpression* lab, SgStatement* st, vector& blocks, const int blockShift, SAPFOR::Argument* arg, bool isComputed) { for (int z = 0; z < num; ++z, lab = lab->rhs()) { SgLabel* lbl = ((SgLabelRefExp*)(lab->lhs()))->label(); auto reg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EQ, arg, createConstArg(isComputed ? (z + 1) : (lbl->getLabNumber())), reg))); const int jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, reg, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(lbl->getLabNumber(), blocks, st); } } static SgStatement* processStatement(SgStatement* st, vector& blocks, map& labels, const FuncInfo* func, const vector>& commonVars, const CFG_Settings& settings) { const bool aloil_flag = settings.atLeastOneIterInLoop; const int var = st->variant(); //printf("%d %d\n", st->lineNumber(), st->variant()); static const set skip = { FORMAT_STAT, OPEN_STAT, CLOSE_STAT, INQUIRE_STAT, REWIND_STAT, BACKSPACE_STAT, ENDFILE_STAT, PAUSE_NODE // <--- TODO }; const int blockShift = blocks.size() != 0 ? blocks[0]->getNumber() : Instruction::getNextInstrNum(); const int firstBlock = blocks.size(); if (var == ASSIGN_STAT) { if (!(st->expr(1)->variant() == CONSTRUCTOR_REF && st->lineNumber() < 0)) // skip init: h(2) = /(2,3) { auto arg1 = processExpression(st->expr(1), blocks, func, commonVars); auto res = processExpression(st->expr(0), blocks, func, commonVars, arg1); if (res) blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, arg1, NULL, res))); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } } else if (var == GOTO_NODE) { addGotoTo(((SgGotoStmt*)st)->branchLabel()->getLabNumber(), blocks, st); processLabel(st, firstBlock, blocks, labels); } else if (var == COMGOTO_NODE) { auto comGoto = isSgComputedGotoStmt(st); auto regCond = processExpression(comGoto->exp(), blocks, func, commonVars); createCompoundGoto(comGoto->numberOfTargets(), comGoto->labelList(), st, blocks, blockShift, regCond, true); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } else if (var == ASSGOTO_NODE) { auto ass = isSgAssignedGotoStmt(st); auto var = createArg(ass->symbol(), commonVars, func); createCompoundGoto(ass->numberOfTargets(), ass->labelList(), st, blocks, blockShift, var, false); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } else if (var == IF_NODE || var == ELSEIF_NODE) { auto ifSt = (SgIfStmt*)(st); auto last = st->lastNodeOfStmt(); for (SgStatement* s = st; s != st->lastNodeOfStmt(); s = s->lexNext()) { if (s->variant() == ELSEIF_NODE && s != st && s->controlParent() == st) { last = s->lexPrev(); break; } } if (ifSt->falseBody()) last = ifSt->falseBody()->lexPrev(); auto regCond = processExpression(ifSt->conditional(), blocks, func, commonVars); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond))); int jump_if = blocks.size() - 1; for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); if (ifSt != last) // not empty { SgStatement* s = st; do { s = s->lexNext(); const int firstInstr = blocks.size(); s = processLabel(processStatement(s, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); } while (s != last); } if (ifSt->falseBody()) { if (var == IF_NODE) addGotoTo(-st->lineNumber(), blocks, st); else // else_if { auto cp = st->controlParent(); while (cp && cp->variant() != IF_NODE) cp = cp->controlParent(); addGotoTo(-cp->lineNumber(), blocks, st); } } blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, (ifSt->falseBody()) ? ifSt->falseBody() : st->lastNodeOfStmt()))); blocks[jump_if]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(blocks.back()->getNumber()))); processLabel(st, firstBlock, blocks, labels); st = last; } else if (var == LOGIF_NODE) { auto ifLog = isSgLogIfStmt(st); auto regCond = processExpression(ifLog->conditional(), blocks, func, commonVars); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond))); int jump_if = blocks.size() - 1; for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(processStatement(ifLog->lexNext(), blocks, labels, func, commonVars, settings), blocks.size(), blocks, labels); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, st))); blocks[jump_if]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(blocks.back()->getNumber()))); processLabel(ifLog, firstBlock, blocks, labels); st = st->lexNext(); } else if (var == ARITHIF_NODE) { SgExpression* cond = st->expr(0); SgExpression* lb = st->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(); } auto regCond = processExpression(st->expr(0), blocks, func, commonVars); auto argZero = createConstArg(0); if (arith_lab[1]->getLabNumber() == arith_lab[2]->getLabNumber()) { auto reg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::LT, regCond, argZero, reg))); const int jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, reg, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(arith_lab[0]->getLabNumber(), blocks); addGotoTo(arith_lab[1]->getLabNumber(), blocks); } else if (arith_lab[0]->getLabNumber() == arith_lab[1]->getLabNumber()) { auto reg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::LE, regCond, argZero, reg))); const int jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, reg, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(arith_lab[1]->getLabNumber(), blocks); addGotoTo(arith_lab[2]->getLabNumber(), blocks); } else { auto reg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::LT, regCond, argZero, reg))); int jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, reg, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(arith_lab[0]->getLabNumber(), blocks); auto reg1 = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EQ, regCond, argZero, reg1))); jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, reg1, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(arith_lab[1]->getLabNumber(), blocks); addGotoTo(arith_lab[2]->getLabNumber(), blocks); } for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } else if (var == FOR_NODE) // MAX (INT ((end - start + step) / step), 0) { SgForStmt* forSt = isSgForStmt(st); SgStatement* last = forSt->lastNodeOfStmt(); auto argZero = createConstArg(0); auto idxArg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, argZero, NULL, idxArg))); auto forArg = createArg(forSt->doName(), commonVars, func); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, processExpression(forSt->start(), blocks, func, commonVars), NULL, forArg))); auto regEnd = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, processExpression(forSt->end(), blocks, func, commonVars), NULL, regEnd))); auto step = forSt->step(); if (!step) step = new SgValueExp(1); auto regStep = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, processExpression(step, blocks, func, commonVars), NULL, regStep))); auto iters = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::SUBT, regEnd, forArg, iters))); auto iters1 = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ADD, iters, regStep, iters1))); auto iters2 = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::DIV, iters1, regStep, iters2))); int jump_cond = -1; int jump_if_N = -1; int loop_body = -1; int loop_body_N = -1; auto regCond = createRegister(); if (aloil_flag == false) { blocks.push_back(new IR_Block(new Instruction(CFG_OP::LT, idxArg, iters2, regCond))); jump_cond = blocks.back()->getNumber(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond))); jump_if_N = blocks.size() - 1; } for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); loop_body = blocks.size(); loop_body_N = blocks.size(); for (auto stF = forSt->lexNext(); stF != last; stF = stF->lexNext()) { const int firstInstr = blocks.size(); stF = processLabel(processStatement(stF, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); } if (loop_body < blocks.size()) loop_body = blocks[loop_body]->getNumber(); else loop_body = -1; // empty loop int gotoNextIter = blocks.back()->getNumber() + 1; int gotoNextIter_N = blocks.size(); int lastNum = blocks.size(); auto tmpReg = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ADD, forArg, regStep, tmpReg, st))); if (loop_body == -1) // empty loop loop_body = blocks.back()->getNumber(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ADD, idxArg, createConstArg(1), idxArg, st))); for (int z = lastNum; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, tmpReg, NULL, forArg, st))); if (aloil_flag == false) blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_cond)), NULL, NULL, st))); else { blocks.push_back(new IR_Block(new Instruction(CFG_OP::GE, idxArg, iters2, regCond, st))); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond, NULL, NULL, st))); jump_if_N = blocks.size() - 1; } findCycleExit(loop_body_N, gotoNextIter_N, CYCLE_STMT, blocks, st, gotoNextIter); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, last))); if (aloil_flag == false) blocks[jump_if_N]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(blocks.back()->getNumber()))); else blocks[jump_if_N]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(loop_body))); findCycleExit(loop_body_N, gotoNextIter_N, EXIT_STMT, blocks, st, blocks.back()->getNumber()); processLabel(forSt, firstBlock, blocks, labels); st = last; } else if (var == WHILE_NODE) { SgWhileStmt* forSt = isSgWhileStmt(st); SgStatement* last = forSt->lastNodeOfStmt(); int firstBlock = blocks.size(); if (forSt->conditional()) { auto regCond = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, processExpression(forSt->conditional(), blocks, func, commonVars), NULL, regCond))); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond, NULL, NULL))); } else blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY))); int jump_if_N = blocks.size() - 1; int first = blocks[firstBlock]->getNumber(); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); for (auto stF = forSt->lexNext(); stF != last; stF = stF->lexNext()) { const int firstInstr = blocks.size(); stF = processLabel(processStatement(stF, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); } findCycleExit(jump_if_N, blocks.size(), CYCLE_STMT, blocks, st, first); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(first)), NULL, NULL, st))); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, last))); if (blocks[jump_if_N]->getInstruction()->getOperation() == CFG_OP::JUMP_IF) blocks[jump_if_N]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(blocks.back()->getNumber()))); findCycleExit(jump_if_N, blocks.size(), EXIT_STMT, blocks, st, blocks.back()->getNumber()); processLabel(forSt, firstBlock, blocks, labels); st = last; } else if (var == STOP_STAT) { blocks.push_back(new IR_Block(new Instruction(CFG_OP::EXIT, st))); processLabel(st, firstBlock, blocks, labels); } else if ((var == CONT_STAT || var == CONTROL_END)) { if (isSgProgHedrStmt(st->controlParent())) blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, st))); else if (st->label()) blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, st))); if (var == CONTROL_END) { auto cp = st->controlParent(); if (cp->variant() == ELSEIF_NODE) { while (cp && cp->variant() != IF_NODE) cp = cp->controlParent(); } if (cp->variant() == IF_NODE) { if (!st->label()) blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, st))); labels[-cp->lineNumber()] = blocks.back()->getInstruction(); } } } else if (var == RETURN_STAT) { auto ret = isSgReturnStmt(st); if (ret->returnValue()) { auto retVal = processExpression(ret->returnValue(), blocks, func, commonVars); blocks.push_back(new IR_Block(new Instruction(CFG_OP::ASSIGN, retVal, NULL, getFuncArg(func->funcName), st))); } blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, st))); // need to add argument processLabel(st, firstBlock, blocks, labels); } else if (var == PROC_STAT) { auto call = isSgCallStmt(st); vector labelsOfArgs; bool hasLabelArgs = processArgs(call, call->numberOfArgs(), blocks, func, commonVars, &labelsOfArgs); string callName = "_ERROR_"; for (int z = 0; z < func->callsFromDetailed.size() && callName == "_ERROR_"; ++z) if (func->callsFromDetailed[z].pointerDetailCallsFrom.first == st) callName = func->callsFromDetailed[z].detailCallsFrom.first; SAPFOR::Argument* fArg = getFuncArg(callName); SAPFOR::Argument* reg = NULL; if (hasLabelArgs) reg = createRegister(); Instruction* instr = new Instruction(CFG_OP::F_CALL, fArg, createConstArg(call->numberOfArgs()), reg); blocks.push_back(new IR_Block(instr)); if (hasLabelArgs) { if (labelsOfArgs.size() == 0 || reg == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (int z = 0; z < labelsOfArgs.size(); ++z) { auto& lab = labelsOfArgs[z]; auto cond = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EQ, reg, createConstArg(z), cond))); const int jump_to = getInstructionNumAfterIfJump(blocks.size(), blockShift, 1); blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, cond, new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(jump_to))))); addGotoTo(lab, blocks); } } for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(call, firstBlock, blocks, labels); } else if (var == PRINT_STAT || var == WRITE_STAT || var == READ_STAT) { SgInputOutputStmt* io = isSgInputOutputStmt(st); SgExpression* item = io->itemList(); vector> items; vector tmp; while (item) { if (item->lhs()->variant() == IOACCESS || item->lhs()->variant() == EXPR_LIST && item->lhs()->lhs()->variant() == IOACCESS || item->lhs()->variant() == EXPR_LIST) { if (tmp.size()) // flush tmp items.push_back(tmp); tmp.clear(); if (item->lhs()->variant() == EXPR_LIST) tmp.push_back(item->lhs()->lhs()); else tmp.push_back(item->lhs()); items.push_back(tmp); tmp.clear(); } else tmp.push_back(item->lhs()); item = item->rhs(); } if (tmp.size()) items.push_back(tmp); else if (tmp.size() == 0 && items.size() == 0) items.push_back(tmp); // empty call for (auto& item : items) { if (item.size() == 1 && item[0]->variant() == IOACCESS) { auto ioAccess = isSgIOAccessExp(item[0]); vector>> loops; SgExpression* body = ioAccess->lhs(); loops.push_back(make_pair(ioAccess->symbol(), make_tuple(ioAccess->rhs()->lhs()->lhs(), ioAccess->rhs()->lhs()->rhs(), ioAccess->rhs()->rhs()))); while (body->variant() == EXPR_LIST) { ioAccess = isSgIOAccessExp(body->lhs()); if (ioAccess) { loops.push_back(make_pair(ioAccess->symbol(), make_tuple(ioAccess->rhs()->lhs()->lhs(), ioAccess->rhs()->lhs()->rhs(), ioAccess->rhs()->rhs()))); body = body->lhs(); } body = body->lhs(); } SgStatement* copyOfSt = st->copyPtr(); ((SgInputOutputStmt*)copyOfSt)->setItemList(*new SgExprListExp(*body)); SgStatement* tmpForStat = NULL; for (int z = loops.size() - 1; z >= 0; --z) { if (z == loops.size() - 1) tmpForStat = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), copyOfSt); else tmpForStat = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), tmpForStat); } processStatement(tmpForStat, blocks, labels, func, commonVars, settings); } else { SgExpression* spec = io->specList(); vector specArgs; if (spec->variant() == SPEC_PAIR) specArgs.push_back(processExpression(spec, blocks, func, commonVars)); else { while (spec) { specArgs.push_back(processExpression(spec->lhs(), blocks, func, commonVars)); spec = spec->rhs(); } } vector args; for (auto& par : item) args.push_back(processExpression(par, blocks, func, commonVars)); for (auto& arg : specArgs) { Instruction* instr = new Instruction(CFG_OP::IO_PARAM, arg); blocks.push_back(new IR_Block(instr)); } for (auto& arg : args) { Instruction* instr = new Instruction(CFG_OP::PARAM, arg); blocks.push_back(new IR_Block(instr)); } SAPFOR::Argument* fArg = NULL; if (var == PRINT_STAT) fArg = getFuncArg("_PRINT"); else if (var == WRITE_STAT) fArg = getFuncArg("_WRITE"); else if (var == READ_STAT) fArg = getFuncArg("_READ"); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Instruction* instr = new Instruction(CFG_OP::F_CALL, fArg, createConstArg(args.size())); blocks.push_back(new IR_Block(instr)); } } for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(io, firstBlock, blocks, labels); } else if (var == CYCLE_STMT || var == EXIT_STMT) { blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, st))); // need to add argument processLabel(st, firstBlock, blocks, labels); } else if (var == SWITCH_NODE) { auto select = isSgSwitchStmt(st); SgStatement* lastSelect = select->lastNodeOfStmt(); int lastNum = blocks.size(); auto condSelect = processExpression(select->selector(), blocks, func, commonVars); for (int z = lastNum; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(select); vector jumpsToEnd; bool hasDef = select->defOption(); int numOfCases = select->numberOfCaseOptions(); for (int z = 0; z < numOfCases; ++z) { auto caseOp = isSgCaseOptionStmt(select->caseOption(z)); SgExpression* caseCond = caseOp->caseRangeList(); if (caseCond->variant() == EXPR_LIST) caseCond = caseCond->lhs(); auto regCond = createRegister(); lastNum = blocks.size(); if (caseCond->variant() == DDOT) { SAPFOR::Argument *left = NULL, *right = NULL; if (caseCond->lhs()) left = processExpression(caseCond->lhs(), blocks, func, commonVars); if (caseCond->rhs()) right = processExpression(caseCond->rhs(), blocks, func, commonVars); if (left && right) { auto tmp1 = createRegister(); auto tmp2 = createRegister(); blocks.push_back(new IR_Block(new Instruction(CFG_OP::GE, condSelect, left, tmp1))); blocks.push_back(new IR_Block(new Instruction(CFG_OP::LE, condSelect, right, tmp2))); blocks.push_back(new IR_Block(new Instruction(CFG_OP::AND, tmp1, tmp2, regCond))); } else if (left) blocks.push_back(new IR_Block(new Instruction(CFG_OP::GE, condSelect, left, regCond))); else blocks.push_back(new IR_Block(new Instruction(CFG_OP::LE, condSelect, right, regCond))); } else { auto condCaseReg = processExpression(caseCond, blocks, func, commonVars); blocks.push_back(new IR_Block(new Instruction(CFG_OP::EQ, condSelect, condCaseReg, regCond))); } blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP_IF, regCond))); for (int z = lastNum; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(caseOp); int jump_if = blocks.size() - 1; SgStatement* body = caseOp->lexNext(); while (body != lastSelect && body->variant() != CASE_NODE && body->variant() != DEFAULT_NODE) { const int firstInstr = blocks.size(); body = processLabel(processStatement(body, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); body = body->lexNext(); } if (hasDef || z != numOfCases - 1) { blocks.push_back(new IR_Block(new Instruction(CFG_OP::JUMP, NULL, NULL, NULL, caseOp))); // to end jumpsToEnd.push_back(blocks.size() - 1); } blocks[jump_if]->getInstruction()->setArg2(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(Instruction::getNextInstrNum()))); } if (hasDef) { SgStatement* body = select->defOption()->lexNext(); while (body != lastSelect && body->variant() != CASE_NODE && body->variant() != DEFAULT_NODE) { const int firstInstr = blocks.size(); body = processLabel(processStatement(body, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); body = body->lexNext(); } } blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, lastSelect))); for (auto& elem : jumpsToEnd) blocks[elem]->getInstruction()->setArg1(new SAPFOR::Argument(CFG_ARG_TYPE::INSTR, to_string(blocks.back()->getNumber()))); processLabel(st, firstBlock, blocks, labels); st = lastSelect; } else if (var == ALLOCATE_STMT || var == DEALLOCATE_STMT) { vector args; for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs()) args.push_back(processExpression(ex->lhs(), blocks, func, commonVars)); for (auto& arg : args) { Instruction* instr = new Instruction(CFG_OP::PARAM, arg); blocks.push_back(new IR_Block(instr)); } SAPFOR::Argument* fArg = NULL; if (var == ALLOCATE_STMT) fArg = getFuncArg("_ALLOC"); else if (var == DEALLOCATE_STMT) fArg = getFuncArg("_DEALLOC"); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Instruction* instr = new Instruction(CFG_OP::F_CALL, fArg, createConstArg(args.size())); blocks.push_back(new IR_Block(instr)); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } else if (var == ASSLAB_STAT) { auto arg = createArg(st->symbol(), commonVars, func); auto labRef = isSgLabelRefExp(st->expr(0)); if (!labRef) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Instruction* instr = new Instruction(CFG_OP::ASSIGN, createConstArg(labRef->label()->getLabNumber()), NULL, arg, st); blocks.push_back(new IR_Block(instr)); } else if (var == ENTRY_STAT) { auto arg = createArg(st->symbol(), commonVars, func); Instruction* instr = new Instruction(CFG_OP::ENTRY, arg, NULL, NULL, st); blocks.push_back(new IR_Block(instr)); processLabel(st, firstBlock, blocks, labels); } else if (var == POINTER_ASSIGN_STAT) { auto pointerAss = isSgPointerAssignStmt(st); SAPFOR::Argument *left, *right; int lVar = pointerAss->lhs()->variant(); if (lVar == VAR_REF || lVar == ARRAY_REF) left = createArg(pointerAss->lhs()->symbol(), commonVars, func); else if (lVar == RECORD_REF) left = processExpression(isSgRecordRefExp(pointerAss->lhs()), blocks, func, commonVars); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); int rVar = pointerAss->rhs()->variant(); if (rVar == VAR_REF || rVar == ARRAY_REF) right = createArg(pointerAss->rhs()->symbol(), commonVars, func); else if (rVar == RECORD_REF) right = processExpression(isSgRecordRefExp(pointerAss->rhs()), blocks, func, commonVars); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); Instruction* instr = new Instruction(CFG_OP::POINTER_ASS, left, NULL, right, st); blocks.push_back(new IR_Block(instr)); for (int z = firstBlock; z < blocks.size(); ++z) blocks[z]->getInstruction()->setOperator(st); processLabel(st, firstBlock, blocks, labels); } else if (isSPF_stat(st) ) { // TODO } else if (isDVM_stat(st)) { if (settings.withDVM) { const int var = st->variant(); // TODO if (var == DVM_PARALLEL_ON_DIR || var == DVM_REDISTRIBUTE_DIR || var == DVM_REALIGN_DIR) { Instruction* instr = new Instruction(CFG_OP::DVM_DIR, NULL, NULL, NULL, st); blocks.push_back(new IR_Block(instr)); } } } else if (skip.find(var) == skip.end() && var > 0) { st->unparsestdout(); __spf_print(1, "unknown statement '%s' on line %d and file %s\n", tag[st->variant()], st->lineNumber(), st->fileName()); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } else { if (var != FORMAT_STAT && var > 0) blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, st))); } return st; } Instruction* getInstructionByNumber(const vector& blocks, int num) { if (blocks.size() == 0) return NULL; const int first = blocks[0]->getNumber(); const int diff = num - first; if (diff < 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (diff >= blocks.size() || diff < blocks.size() && blocks[diff]->getNumber() != num) { printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& elem : blocks) if (elem->getNumber() == num) return elem->getInstruction(); } else return blocks[diff]->getInstruction(); } pair getInstructionAndBlockByNumber(const map>& CFGraph, int num) { if (num < 0) return { NULL, NULL }; for (const auto& byFunc : CFGraph) for (auto byBB : byFunc.second) if (byBB->getInstructions().front()->getNumber() <= num && byBB->getInstructions().back()->getNumber() >= num) return make_pair(getInstructionByNumber(byBB->getInstructions(), num), byBB); printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return { NULL, NULL }; } pair getInstructionAndBlockByStatement(const map>& CFGraph, SgStatement* stmt) { SgStatement* cur = stmt; while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR) cur = cur->controlParent(); string funcName = ((SgProcHedrStmt*)cur)->nameWithContains(); int stmtID = stmt->id(); for (const auto& funcCFG : CFGraph) { if (funcCFG.first->funcName != funcName) continue; for (auto basicBlock : funcCFG.second) for (auto ins : basicBlock->getInstructions()) if (stmtID == ins->getInstruction()->getOperator()->id()) return make_pair(ins->getInstruction(), basicBlock); } printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return { NULL, NULL }; } int getParamIndex(SAPFOR::Argument* func_param, int max_index) { if (func_param->getMemType() != SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); string name = func_param->getValue(); int num = stoi(name.substr(name.rfind('%') + 1)); if (num < 0 || num >= max_index) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return num; } vector buildIR(SgStatement* function, const FuncInfo* func, const vector>& commonVars, const CFG_Settings settings) { vector blocks; map labels; SgStatement* end = function->lastNodeOfStmt(); SgStatement* st = function; do { st = st->lexNext(); if (st->variant() == CONTAINS_STMT) st = end; if (!isSgExecutableStatement(st) && st->variant() != ENTRY_STAT) continue; const int firstInstr = blocks.size() ? blocks.size() : 1; st = processLabel(processStatement(st, blocks, labels, func, commonVars, settings), firstInstr, blocks, labels); } while (st != end); if (blocks.back()->getInstruction()->getOperator() != end) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); else findReturn(0, blocks.size(), blocks, blocks.back()->getNumber()); // добавление связей по GOTO и переходам for (int z = 0; z < blocks.size(); ++z) { auto op = blocks[z]->getInstruction()->getOperation(); if (op == CFG_OP::JUMP || op == CFG_OP::JUMP_IF) { auto arg = (op == CFG_OP::JUMP) ? blocks[z]->getInstruction()->getArg1() : blocks[z]->getInstruction()->getArg2(); if (arg == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const int lab = std::stoi(arg->getValue()); if (arg->getType() == CFG_ARG_TYPE::LAB) { auto it = labels.find(lab); if (it == labels.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); blocks[z]->setJump(it->second); // заменим метку на номер инструкции arg->setValue(to_string(it->second->getNumber())); arg->setType(CFG_ARG_TYPE::INSTR); } else if (arg->getType() == CFG_ARG_TYPE::INSTR) blocks[z]->setJump(getInstructionByNumber(blocks, lab)); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } } for (auto& ir : blocks) if (ir->getInstruction()->getOperator() == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& elem : dictArgs) dictArgsByArg[elem.second.first] = elem.second.second; return blocks; } enum VisitState { UNVISITED = 0, VISITING = 1, VISITED = 2 }; void dfs(SAPFOR::BasicBlock* block, map& visit, vector>& startAndEnd, SAPFOR::BasicBlock* prev) { if (!block) return; if (visit[block->getNumber()] == VISITED) { cout << "error"; return; } if (visit[block->getNumber()] == VISITING) { visit[block->getNumber()] = VISITED; startAndEnd.push_back(make_pair(prev, block)); return; } visit[block->getNumber()] = VISITING; for (auto i : block->getNext()) { dfs(i, visit, startAndEnd, block); } } static void printBlock(SAPFOR::BasicBlock* block) { cout << "block - " << block->getNumber() << endl; cout << "next -"; for (auto i : block->getNext()) { cout << " " << i->getNumber(); } cout << endl << "prev -"; for (auto i : block->getPrev()) { cout << " " << i->getNumber(); } cout << endl; for (auto i : block->getInstructions()) { string resValue = ""; string arg1Value = ""; string arg2Value = ""; if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) { resValue = i->getInstruction()->getResult()->getValue(); i->getInstruction()->getResult()->setValue(i->getInstruction()->getResult()->getValue() + to_string(i->getInstruction()->getResult()->getNumber())); } if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) { arg1Value = i->getInstruction()->getArg1()->getValue(); i->getInstruction()->getArg1()->setValue(i->getInstruction()->getArg1()->getValue() + to_string(i->getInstruction()->getArg1()->getNumber())); } if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) { arg2Value = i->getInstruction()->getArg2()->getValue(); i->getInstruction()->getArg2()->setValue(i->getInstruction()->getArg2()->getValue() + to_string(i->getInstruction()->getArg2()->getNumber())); } cout << i->getNumber() << " " << i->getInstruction()->dump() << endl; if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) { i->getInstruction()->getResult()->setValue(resValue); } if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) { i->getInstruction()->getArg1()->setValue(arg1Value); } if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) { i->getInstruction()->getArg2()->setValue(arg2Value); } } cout << endl; } void getLoopBody(SAPFOR::BasicBlock* loopHeader, const std::set& loopExits, std::vector& loopBody) { std::set visited; std::stack stack; stack.push(loopHeader); while (!stack.empty()) { auto block = stack.top(); stack.pop(); if (visited.count(block)) continue; visited.insert(block); for (auto succ : block->getNext()) { if (loopExits.count(succ)) continue; if (!visited.count(succ)) { stack.push(succ); } } } std::set backReachable; std::stack reverseStack; reverseStack.push(loopHeader); while (!reverseStack.empty()) { auto block = reverseStack.top(); reverseStack.pop(); if (backReachable.count(block)) continue; backReachable.insert(block); for (auto pred : block->getPrev()) { if (visited.count(pred) && !backReachable.count(pred)) { reverseStack.push(pred); } } } for (auto block : visited) { if (backReachable.count(block)) { loopBody.push_back(block); } } } set findRegisterSourceVariables(const std::vector& blocks, SAPFOR::Argument* var) { std::set result; std::set visited; std::stack workStack; workStack.push(var); auto isBinaryOp = [](SAPFOR::CFG_OP op) { return op == SAPFOR::CFG_OP::ADD || op == SAPFOR::CFG_OP::SUBT || op == SAPFOR::CFG_OP::MULT || op == SAPFOR::CFG_OP::DIV || op == SAPFOR::CFG_OP::POW || op == SAPFOR::CFG_OP::GE || op == SAPFOR::CFG_OP::LE || op == SAPFOR::CFG_OP::GT || op == SAPFOR::CFG_OP::LT || op == SAPFOR::CFG_OP::EQ || op == SAPFOR::CFG_OP::NEQV || op == SAPFOR::CFG_OP::EQV || op == SAPFOR::CFG_OP::EMPTY || op == SAPFOR::CFG_OP::OR || op == SAPFOR::CFG_OP::AND; }; auto isUnaryOp = [](SAPFOR::CFG_OP op) { return op == SAPFOR::CFG_OP::UN_ADD || op == SAPFOR::CFG_OP::UN_MINUS || op == SAPFOR::CFG_OP::NOT || op == SAPFOR::CFG_OP::ASSIGN; }; while (!workStack.empty()) { auto variable = workStack.top(); workStack.pop(); if (!variable || visited.count(variable)) continue; visited.insert(variable); for (auto block : blocks) { for (auto instrWrapper : block->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (!instr || instr->getResult() != variable) continue; auto op = instr->getOperation(); auto arg1 = instr->getArg1(); auto arg2 = instr->getArg2(); if (isBinaryOp(op) && arg1 && arg2) { if (arg1->getType() == CFG_ARG_TYPE::VAR) result.insert(arg1); else if (arg1->getType() == CFG_ARG_TYPE::REG) workStack.push(arg1); if (arg2->getType() == CFG_ARG_TYPE::VAR) result.insert(arg2); else if (arg2->getType() == CFG_ARG_TYPE::REG) workStack.push(arg2); } else if (isUnaryOp(op) && arg1) { if (arg1->getType() == CFG_ARG_TYPE::VAR) result.insert(arg1); else if (arg1->getType() == CFG_ARG_TYPE::REG) workStack.push(arg1); } } } } return result; } std::vector getPhiArguments(SAPFOR::BasicBlock* block, SAPFOR::Instruction* phiInstr) { std::vector result; auto& instructions = block->getInstructions(); bool collecting = false; for (int i = instructions.size() - 1; i >= 0; --i) { auto instr = instructions[i]->getInstruction(); if (collecting) { if (instr->getOperation() == SAPFOR::CFG_OP::PARAM) { auto arg = instr->getArg1(); if (arg) { result.push_back(instr); } } else { break; } } if (!instr) continue; if (instr == phiInstr) { collecting = true; continue; } } std::reverse(result.begin(), result.end()); return result; } SAPFOR::BasicBlock* findInstructionBlock(SAPFOR::Instruction* targetInstr, const std::vector& blocks) { for (auto block : blocks) { for (auto instrWrapper : block->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (instr == targetInstr) { return block; } } } return nullptr; } SAPFOR::BasicBlock* findInstructionBlockByNumber(int number, const std::vector& blocks) { for (auto block : blocks) { for (auto instrWrapper : block->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (instr->getNumber() == number) { return block; } } } return nullptr; } void findInductiveVars(const std::vector& blocks, const std::vector& Loopblocks, SAPFOR::BasicBlock* loopHeader, const std::set& loopExits) { std::set inductiveVars; std::set relevantBlocks = { loopHeader }; for (auto block : relevantBlocks) { for (auto instrWrapper : block->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (!instr) continue; auto op = instr->getOperation(); auto res = instr->getResult(); auto arg1 = instr->getArg1(); auto arg2 = instr->getArg2(); if (op == CFG_OP::JUMP_IF) { if (arg1 && arg1->getType() == CFG_ARG_TYPE::VAR) { inductiveVars.insert(arg1->getValue()); } if (arg1 && arg1->getType() == CFG_ARG_TYPE::REG) { auto foundVariables = findRegisterSourceVariables(blocks, arg1); for (auto var : foundVariables) { inductiveVars.insert(var->getValue()); } } } } } std::set finalInductiveVars; for (auto instrWrapper : loopHeader->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (!instr || instr->getOperation() != SAPFOR::CFG_OP::F_CALL || !instr->getArg1() || instr->getArg1()->getValue() != "FI_FUNCTION") continue; auto phiRes = instr->getResult(); if (!phiRes || !inductiveVars.count(phiRes->getValue())) continue; auto currentBlock = findInstructionBlock(instr, blocks); if (!currentBlock) continue; auto phiArgs = getPhiArguments(currentBlock, instr); bool hasInLoopDefinition = false; for (const auto& argInstr : phiArgs) { if (!argInstr) continue; int definitionInstrNumber = stoi(argInstr->getArg1()->getValue()); if (definitionInstrNumber == -1) continue; auto phiBlock = findInstructionBlockByNumber(definitionInstrNumber, blocks); if (!phiBlock) continue; if (std::find(Loopblocks.begin(), Loopblocks.end(), phiBlock) != Loopblocks.end()) { hasInLoopDefinition = true; } } if (hasInLoopDefinition) { finalInductiveVars.insert(phiRes->getValue()); } } for (auto i : finalInductiveVars) { std::cout << "Confirmed inductive variable: " << i << std::endl; } if (finalInductiveVars.empty()) { std::cout << "No confirmed inductive variables found." << std::endl; } } Instruction* findInstructionAfterLoop(const std::vector& loopBody) { std::set loopSet(loopBody.begin(), loopBody.end()); for (auto block : loopBody) { for (auto succ : block->getNext()) { if (!loopSet.count(succ)) { // Нашли выход из цикла — возьмём первую инструкцию auto instructions = succ->getInstructions(); for (auto wrapper : instructions) { if (auto instr = wrapper->getInstruction()) { return instr; } } } } } return nullptr; // не нашли } void exploreLoops(map>* fullIR) { for (auto& i : *fullIR) { //for (auto j : i.second) // printBlock(j); map visited; for (auto i : i.second) visited[i->getNumber()] = UNVISITED; //vector visited(i.second.size(), UNVISITED); vector> startAndEnd; dfs(i.second[0], visited, startAndEnd, NULL); vector loops; for (auto& [tail, header] : startAndEnd) { set loopExits; for (auto succ : tail->getNext()) { if (succ != header) { loopExits.insert(succ); } } vector loopBody; getLoopBody(header, loopExits, loopBody); cout << "LOOP DETECTED:" << endl; cout << " Header: " << header->getNumber() << endl; cout << " Tail: " << tail->getNumber() << endl; cout << " Body blocks: "; for (auto block : loopBody) { cout << block->getNumber() << " "; } cout << endl; findInductiveVars(i.second, loopBody, header, loopExits); Instruction* instructionAfterLoop = findInstructionAfterLoop(loopBody); if (instructionAfterLoop == NULL) { cout << "Warning: instruction after loop not found!" << endl; continue; } auto firstInstruction = header->getInstructions()[0]->getInstruction(); auto lastInstruction = tail->getInstructions().back()->getInstruction(); cout << "first - " << firstInstruction->getNumber() << " last - " << lastInstruction->getNumber() << " after - " << instructionAfterLoop->getNumber() << endl; auto x = firstInstruction->getOperator(); auto tmpLoop = new LoopGraph(); tmpLoop->isFor = true; tmpLoop->lineNum = firstInstruction->getOperator()->lineNumber(); tmpLoop->lineNumAfterLoop = instructionAfterLoop->getOperator()->lineNumber(); if (firstInstruction->getOperator()->variant() == FOR_NODE) { SgForStmt* stmt = isSgForStmt(firstInstruction->getOperator()); cout << "for loop" << endl << stmt->sunparse() << endl; } else if (firstInstruction->getOperator()->variant() == WHILE_NODE) { SgWhileStmt* stmt = isSgWhileStmt(firstInstruction->getOperator()); cout << (stmt->conditional() == NULL ? "infinit" : "") << "while loop" << endl << stmt->sunparse() << endl; } else if (firstInstruction->getOperator()->variant() == DO_WHILE_NODE) { SgWhileStmt* stmt = isSgDoWhileStmt(firstInstruction->getOperator()); cout << "do while loop" << endl << stmt->sunparse() << endl; } else if (firstInstruction->getOperator()->variant() == LOOP_NODE) { cout << "not known loop" << endl << firstInstruction->getOperator()->sunparse() << endl; } else { cout << "goto loop" << firstInstruction->getOperator()->sunparse() << endl; } cout << "loop start line " << tmpLoop->lineNum << endl; cout << "after loop line " << tmpLoop->lineNumAfterLoop << endl << endl; loops.push_back(tmpLoop); } } }