#pragma once #include #include #include #include #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 instructions; std::vector next; std::vector prev; BasicBlock* idom{}; //reaching definition std::map> RD_in, RD_out; //live variables [arg -> blocks with usages] std::map> live_in, live_out, live_inout; bool addLive(const std::map>& to_add, bool in); std::map> 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_); } void setIdom(BasicBlock* idom_) { idom = idom_; } int removePrev(BasicBlock* removed); int removeNext(BasicBlock* removed); void replacePrevNext(const std::map& 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& getInstructions() const { return instructions; } const std::vector& getNext() const { return next; } const std::vector& getPrev() const { return prev; } BasicBlock* getIdom() const { return idom; } /* * FOR LIVE ANALYSIS */ bool addLiveIn(const std::map>& to_add) { return addLive(to_add, true); }; bool addLiveOut(const std::map>& 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> getLiveIn() const { return getLive(true); }; std::map> getLiveOut() const { return getLive(false); }; void compressLives(); /* * FOR REACHING DEFINITIONS */ void setRD_In(const std::map>& inSet) { RD_in = inSet; } void setRD_Out(const std::map>& outSet) { RD_out = outSet; } const std::map>& getRD_In() const { return RD_in; } const std::map>& getRD_Out() const { return RD_out; } std::map>& getModRD_In() { return RD_in; } std::map>& 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> buildCFG(const std::map& commonBlocks, const std::map>& allFuncInfo, const SAPFOR::CFG_Settings settings); std::map> buildCFGforCurrentFunc(SgStatement* stmt, SAPFOR::CFG_Settings settings, const std::map& commonBlocks, const std::map>& allFuncInfo); std::vector> getCommonsByFunction(SgFile* file, SgStatement* function, const std::map& commonBlocks); std::vector getAllIR(const std::vector& blocks); void dumpCFG(const std::map>& blocks, bool withRD); std::vector> groupByCallDependencies(const std::map>& callDeps, std::vector>& scc); template bool intersectAndAdd(std::set& s1, const std::set& s2); void buildGenKillForCFG(const std::vector& CFG, const std::map& funcByName, const std::map>>& outForFunc, std::map>>& gen, std::map>>& kill, std::map>>* genForIR, std::map>>* killForIR, std::map>& notInitedGlobals, const SAPFOR::CFG_Settings settings); static inline void deleteCFG(std::map>& cfg) { for (auto& byFunc : cfg) { for (auto& block : byFunc.second) delete block; byFunc.second.clear(); } cfg.clear(); }