2025-06-02 19:08:09 +03:00
|
|
|
#include "leak_detector.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <set>
|
|
|
|
|
|
2025-06-04 13:08:38 +03:00
|
|
|
#include "SgUtils.h"
|
|
|
|
|
#include "CommonBlock.h"
|
2025-06-02 19:08:09 +03:00
|
|
|
#include "graph_calls.h"
|
|
|
|
|
#include "expr_transform.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
#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();
|
2025-05-30 12:29:35 +03:00
|
|
|
if ((var == VAR_REF || var == CONST_REF || var == LABEL_REF) && !ex->lhs() && !ex->rhs()) // variable reference
|
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();
|
2025-05-27 02:25:39 +03:00
|
|
|
Instruction* instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(numArgs), isLeft ? isLeft : reg, NULL, ex);
|
2023-09-14 19:43:13 +03:00
|
|
|
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();
|
2025-05-27 02:25:39 +03:00
|
|
|
instr = new Instruction(isLeft ? CFG_OP::STORE : CFG_OP::LOAD, arg1, createConstArg(1), isLeft ? isLeft : reg, NULL, ex);
|
2023-09-14 19:43:13 +03:00
|
|
|
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_";
|
2023-11-05 13:08:57 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2025-05-27 02:25:39 +03:00
|
|
|
Instruction* instr = new Instruction(CFG_OP::LOAD, arg, NULL, reg, NULL, ex);
|
2023-09-14 19:43:13 +03:00
|
|
|
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_";
|
2023-11-05 13:08:57 +03:00
|
|
|
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());
|
|
|
|
|
|
2025-05-30 12:29:35 +03:00
|
|
|
// adding links by GOTO and jumps
|
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);
|
|
|
|
|
|
2025-05-30 12:29:35 +03:00
|
|
|
// replacing the label with the instruction number
|
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;
|
|
|
|
|
}
|