Files
SAPFOR/src/CFGraph/IR.cpp

1752 lines
70 KiB
C++
Raw Normal View History

2023-09-14 19:43:13 +03:00
#include "../Utils/leak_detector.h"
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <set>
#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<string, pair<SAPFOR::Argument*, pair<string, SgSymbol*>>> dictArgs;
static map<SAPFOR::Argument*, pair<string, SgSymbol*>> dictArgsByArg;
static int lastNumReg = 0;
int Argument::lastNumArg = 0;
int Instruction::lastNumInstr = 0;
static SAPFOR::Argument* processExpression(SgExpression* ex, vector<IR_Block*>& blocks, const FuncInfo* func,
const vector<pair<const Variable*, CommonBlock*>>& 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<pair<const Variable*, CommonBlock*>>& 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<pair<const Variable*, CommonBlock*>>& 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)
2024-04-13 18:14:28 +03:00
newName = string("%") + "key_arg_" + isSgKeywordValExp(exp)->value();
2023-09-14 19:43:13 +03:00
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<IR_Block*>& blocks, const FuncInfo* func, int& numArgs,
const vector<pair<const Variable*, CommonBlock*>>& 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<tuple<int, SAPFOR::Argument*, SAPFOR::Argument*, SAPFOR::Argument*>> 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<typename funcStatement>
static bool processArgs(funcStatement* call, int num, vector<IR_Block*>& blocks, const FuncInfo* func,
const vector<pair<const Variable*, CommonBlock*>>& commonVars, vector<int>* labels = NULL)
{
bool hasLabelArg = false;
vector<SAPFOR::Argument*> 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<IR_Block*>& blocks, const FuncInfo* func,
const vector<pair<const Variable*, CommonBlock*>>& commonVars, SAPFOR::Argument* isLeft)
{
static map<int, CFG_OP> 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();
2024-11-22 00:28:12 +03:00
if ((var == VAR_REF || var == CONST_REF || var == LABEL_REF) && !ex->lhs() && !ex->rhs()) // обращение к переменной
2023-09-14 19:43:13 +03:00
{
if (var == CONST_REF)
{
SgExpression* value = CalculateInteger(ex->copyPtr());
if (isSgValueExp(value))
return createConstArg(value);
else
return createArg(ex->symbol(), commonVars, func);
}
2024-04-13 18:14:28 +03:00
else if (var == LABEL_REF)
{
auto labRef = isSgLabelRefExp(ex);
if (labRef == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return createConstArg(labRef->label()->getLabNumber());
}
2023-09-14 19:43:13 +03:00
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;
2023-09-14 19:43:13 +03:00
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<SgExpression*> 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);
2024-04-13 18:14:28 +03:00
else if (var == SPEC_PAIR)
return processExpression(ex->rhs(), blocks, func, commonVars);
2023-09-14 19:43:13 +03:00
else
{
__spf_print(1, "unknown expression '%s'\n", tag[ex->variant()]);
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
2024-04-13 18:14:28 +03:00
2023-09-14 19:43:13 +03:00
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return NULL;
}
static SgStatement* processLabel(SgStatement* st, const int firstInstr, const vector<IR_Block*>& blocks, map<int, Instruction*>& 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<IR_Block*>& 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<IR_Block*>& 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<IR_Block*>& 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<IR_Block*>& 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<IR_Block*>& blocks, map<int, Instruction*>& labels, const FuncInfo* func,
const vector<pair<const Variable*, CommonBlock*>>& commonVars, const CFG_Settings& settings)
{
const bool aloil_flag = settings.atLeastOneIterInLoop;
const int var = st->variant();
//printf("%d %d\n", st->lineNumber(), st->variant());
2023-11-29 14:08:12 +03:00
static const set<int> skip = { FORMAT_STAT, OPEN_STAT, CLOSE_STAT, INQUIRE_STAT, REWIND_STAT, BACKSPACE_STAT,
ENDFILE_STAT, PAUSE_NODE // <--- TODO
2023-09-14 19:43:13 +03:00
};
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);
}
}
2023-12-02 10:20:13 +03:00
blocks.push_back(new IR_Block(new Instruction(CFG_OP::EMPTY, (ifSt->falseBody()) ? ifSt->falseBody() : st->lastNodeOfStmt())));
2023-09-14 19:43:13 +03:00
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<int> 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;
2023-09-14 19:43:13 +03:00
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);
2024-04-13 18:14:28 +03:00
2023-09-14 19:43:13 +03:00
SgExpression* item = io->itemList();
vector<vector<SgExpression*>> items;
vector<SgExpression*> 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<pair<SgSymbol*, tuple<SgExpression*, SgExpression*, SgExpression*>>> 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
{
2024-04-13 18:14:28 +03:00
SgExpression* spec = io->specList();
vector<SAPFOR::Argument*> 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();
}
}
2023-09-14 19:43:13 +03:00
vector<SAPFOR::Argument*> args;
for (auto& par : item)
args.push_back(processExpression(par, blocks, func, commonVars));
2024-04-13 18:14:28 +03:00
for (auto& arg : specArgs)
{
Instruction* instr = new Instruction(CFG_OP::IO_PARAM, arg);
blocks.push_back(new IR_Block(instr));
}
2023-09-14 19:43:13 +03:00
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<int> 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();
2023-10-10 16:38:27 +03:00
while (body != lastSelect &&
body->variant() != CASE_NODE &&
body->variant() != DEFAULT_NODE)
2023-09-14 19:43:13 +03:00
{
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<SAPFOR::Argument*> 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<IR_Block*>& 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<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByNumber(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& 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<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByStatement(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& 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<IR_Block*> buildIR(SgStatement* function, const FuncInfo* func, const vector<pair<const Variable*, CommonBlock*>>& commonVars, const CFG_Settings settings)
{
vector<IR_Block*> blocks;
map<int, Instruction*> 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());
2024-11-22 00:28:12 +03:00
// добавление связей по GOTO и переходам
2023-09-14 19:43:13 +03:00
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);
2024-11-22 00:28:12 +03:00
// заменим метку на номер инструкции
2023-09-14 19:43:13 +03:00
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;
}
2024-05-26 12:32:53 +03:00
void dfs(SAPFOR::BasicBlock* block, vector<int>& visit, vector<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>>& startAndEnd, SAPFOR::BasicBlock* prev) {
if (visit[block->getNumber()] == 2) {
cout << "error";
return;
}
if (visit[block->getNumber()] == 1) {
visit[block->getNumber()] = 2;
startAndEnd.push_back(make_pair(prev, block));
return;
}
visit[block->getNumber()] = 1;
for (auto i : block->getNext()) {
dfs(i, visit, startAndEnd, block);
}
}
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())
{
cout << i->getNumber() << " " << i->getInstruction()->dump() << endl;
}
cout << endl;
}
void testIR(map<FuncInfo*, vector<SAPFOR::BasicBlock*>> fullIR) {
for (auto& i : fullIR)
{
for (auto j : i.second)
printBlock(j);
2024-05-26 13:53:47 +03:00
vector<IR_Block*> all;
for (auto j : i.second)
for (auto k : j->getInstructions())
all.push_back(k);
2024-05-26 12:32:53 +03:00
vector<int> visited(i.second.size(), 0);
vector<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> startAndEnd;
dfs(i.second[0], visited, startAndEnd, NULL);
vector<LoopGraph*> loops;
for (auto j : startAndEnd)
{
2024-05-26 13:53:47 +03:00
auto firstInstruction = j.second->getInstructions()[0]->getInstruction();
auto lastInstruction = j.first->getInstructions().back()->getInstruction();
Instruction* instructionAfterLoop;
for (auto a : fullIR)
for(auto b : a.second)
for (auto c : b->getInstructions())
if (c->getInstruction()->getNumber() == lastInstruction->getNumber() + 1)
{
instructionAfterLoop = c->getInstruction();
break;
}
//auto instructionAfterLoop = getInstructionByNumber(all, lastInstruction->getNumber() + 1);
cout << "first - " << firstInstruction->getNumber() << " last - " << lastInstruction->getNumber() << " after - " << instructionAfterLoop->getNumber() << endl;
if (firstInstruction->getOperator()->variant() == FOR_NODE) {
SgForStmt* stmt = isSgForStmt(firstInstruction->getOperator());
2024-05-26 12:32:53 +03:00
auto tmpLoop = new LoopGraph();
tmpLoop->isFor = true;
2024-05-26 13:53:47 +03:00
tmpLoop->lineNum = firstInstruction->getOperator()->lineNumber();
tmpLoop->lineNumAfterLoop = instructionAfterLoop->getOperator()->lineNumber();
2024-05-26 12:32:53 +03:00
cout << "for" << endl << stmt->sunparse() << endl;
2024-05-26 13:53:47 +03:00
cout << "loop start line " << tmpLoop->lineNum << endl;
cout << "after loop line " << tmpLoop->lineNumAfterLoop << endl << endl;
2024-05-26 12:32:53 +03:00
loops.push_back(tmpLoop);
2024-05-26 13:53:47 +03:00
} else if (firstInstruction->getOperator()->variant() == WHILE_NODE) {
SgWhileStmt* stmt = isSgWhileStmt(firstInstruction->getOperator());
2024-05-26 12:32:53 +03:00
auto tmpLoop = new LoopGraph();
2024-05-26 13:53:47 +03:00
tmpLoop->lineNum = firstInstruction->getOperator()->lineNumber();
tmpLoop->lineNumAfterLoop = instructionAfterLoop->getOperator()->lineNumber();
2024-05-26 12:32:53 +03:00
if (stmt->conditional() == NULL)
{
//infinit loop
cout << "infinit loop " << endl << stmt->sunparse() << endl;
}
else
{
//while
cout << "while " << endl << stmt->sunparse();
}
2024-05-26 13:53:47 +03:00
cout << "loop start line " << tmpLoop->lineNum << endl;
cout << "after loop line " << tmpLoop->lineNumAfterLoop << endl << endl;
2024-05-26 12:32:53 +03:00
loops.push_back(tmpLoop);
2024-05-26 13:53:47 +03:00
} else if (firstInstruction->getOperator()->variant() == LOOP_NODE) {
cout << "not known loop" << endl << firstInstruction->getOperator()->sunparse() << endl;
2024-05-26 12:32:53 +03:00
}
else {
2024-05-26 13:53:47 +03:00
cout << "goto loop - " << firstInstruction->getOperator()->sunparse() << endl;
2024-05-26 12:32:53 +03:00
}
}
/*for (auto j : i.second) {
cout << j->getNumber() << endl << "in" << endl;
for (auto k : j->getRD_In()) {
cout << k.first->getMemTypeStr() << " - ";
for (auto h : k.second) {
cout << h << " ";
}
cout << endl;
}
cout << "out" << endl;
for (auto k : j->getRD_Out()) {
cout << k.first->getMemTypeStr() << " - ";
for (auto h : k.second) {
cout << h << " ";
}
cout << endl;
}*/
}
}