149 lines
6.8 KiB
C++
149 lines
6.8 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 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();
|
|
} |