Files
SAPFOR/Sapfor/_src/CFGraph/CFGraph.h
2025-03-25 20:39:29 +03:00

151 lines
6.9 KiB
C++

#pragma once
#include <string>
#include <map>
#include <set>
#include <vector>
#include "IR.h"
namespace SAPFOR
{
enum CFG_VAL : int { KILL_ALL = -1, UNINIT = -2 };
class IR_Block;
class Argument;
class Instruction;
class BasicBlock
{
static int lastNumBlock;
private:
int num;
std::vector<IR_Block*> instructions;
std::vector<BasicBlock*> next;
std::vector<BasicBlock*> prev;
//reaching definition
std::map<SAPFOR::Argument*, std::set<int>> RD_in, RD_out;
//live variables [arg -> blocks with usages]
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> live_in, live_out, live_inout;
bool addLive(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add, bool in);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLive(bool in) const;
bool removeLive(SAPFOR::Argument* to_remove, bool in);
public:
BasicBlock() { num = lastNumBlock++; }
BasicBlock(IR_Block* item);
BasicBlock(const BasicBlock& copyFrom);
void addInstructionBeforeInstruction(IR_Block* item, Instruction* istruction);
void addInstructionInFront(IR_Block* item);
void addInstruction(IR_Block* item);
void addPrev(BasicBlock* prev_) { prev.push_back(prev_); }
void addNext(BasicBlock* next_) { next.push_back(next_); }
int removePrev(BasicBlock* removed);
int removeNext(BasicBlock* removed);
void replacePrevNext(const std::map<BasicBlock*, BasicBlock*>& oldToNew)
{
for (int z = 0; z < next.size(); ++z)
{
auto it = oldToNew.find(next[z]);
if (it == oldToNew.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
next[z] = it->second;
}
for (int z = 0; z < prev.size(); ++z)
{
auto it = oldToNew.find(prev[z]);
if (it == oldToNew.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
prev[z] = it->second;
}
}
int getNumber() const { return num; }
const std::vector<IR_Block*>& getInstructions() const { return instructions; }
const std::vector<BasicBlock*>& getNext() const { return next; }
const std::vector<BasicBlock*>& getPrev() const { return prev; }
/*
* FOR LIVE ANALYSIS
*/
bool addLiveIn(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
bool addLiveOut(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, false); };
bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); };
bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); };
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
void compressLives();
/*
* FOR REACHING DEFINITIONS
*/
void setRD_In(const std::map<Argument*, std::set<int>>& inSet) { RD_in = inSet; }
void setRD_Out(const std::map<Argument*, std::set<int>>& outSet) { RD_out = outSet; }
const std::map<Argument*, std::set<int>>& getRD_In() const { return RD_in; }
const std::map<Argument*, std::set<int>>& getRD_Out() const { return RD_out; }
std::map<Argument*, std::set<int>>& getModRD_In() { return RD_in; }
std::map<Argument*, std::set<int>>& getModRD_Out() { return RD_out; }
~BasicBlock();
};
struct CFG_Settings
{
bool atLeastOneIterInLoop = false;
bool withRD = true;
bool withRegisters = false;
bool withSPF = false;
bool withDVM = false;
bool withCallsInBlocks = false; // separate each F_CALL to own BasicBlock
bool withCallFrom = true;
explicit CFG_Settings(int) { }
explicit CFG_Settings(bool atLeastOneIterInLoop = false, bool withRD = true, bool withRegisters = false,
bool withDVM = false, bool withSPF = false, bool withCallsInBlocks = false, bool withCallFrom = true) :
atLeastOneIterInLoop(atLeastOneIterInLoop), withRD(withRD), withRegisters(withRegisters), withDVM(withDVM), withSPF(withSPF),
withCallsInBlocks(withCallsInBlocks), withCallFrom(withCallFrom)
{ }
};
}
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFG(const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const SAPFOR::CFG_Settings settings);
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFGforCurrentFunc(SgStatement* stmt, SAPFOR::CFG_Settings settings, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
std::vector<std::pair<const Variable*, CommonBlock*>> getCommonsByFunction(SgFile* file, SgStatement* function, const std::map<std::string, CommonBlock*>& commonBlocks);
std::vector<SAPFOR::IR_Block*> getAllIR(const std::vector<SAPFOR::BasicBlock*>& blocks);
void dumpCFG(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& blocks, bool withRD);
std::vector<std::set<FuncInfo*>> groupByCallDependencies(const std::map<FuncInfo*, std::set<FuncInfo*>>& callDeps, std::vector<std::set<FuncInfo*>>& scc);
template<typename T>
bool intersectAndAdd(std::set<T>& s1, const std::set<T>& s2);
void buildGenKillForCFG(const std::vector<SAPFOR::BasicBlock*>& CFG,
const std::map<std::string, FuncInfo*>& funcByName,
const std::map<FuncInfo*, std::map<SAPFOR::Argument*, std::set<int>>>& outForFunc,
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& gen,
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& kill,
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* genForIR,
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* killForIR,
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::Argument*>>& notInitedGlobals,
const SAPFOR::CFG_Settings settings);
static inline void deleteCFG(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& cfg)
{
for (auto& byFunc : cfg)
{
for (auto& block : byFunc.second)
delete block;
byFunc.second.clear();
}
cfg.clear();
}