178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
#pragma once
|
|
#include <deque>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include "IR/IR_basic.h"
|
|
using CFGNodeCollection = std::list<class CFGNodeType *>;
|
|
class CFGNodeType {
|
|
public:
|
|
// successors, predecessors, corresponding_block is provided by BuildCFGForFunction
|
|
std::vector<CFGNodeType *> successors, predecessors;
|
|
BlockItem *corresponding_block;
|
|
// the following fields are provided by user
|
|
CFGNodeCollection dom;
|
|
bool visited;
|
|
CFGNodeType *idom;
|
|
std::vector<CFGNodeType *> successors_in_dom_tree;
|
|
CFGNodeCollection dom_frontier;
|
|
|
|
std::vector<size_t> block_in_active_vars;
|
|
std::vector<size_t> block_out_active_vars;
|
|
std::vector<size_t> block_use_vars;
|
|
std::vector<size_t> block_def_vars;
|
|
|
|
std::unordered_map<ActionItem *, std::vector<size_t>> action_use_vars;
|
|
std::unordered_map<ActionItem *, std::vector<size_t>> action_def_vars;
|
|
std::unordered_map<ActionItem *, std::vector<size_t>> action_in_active_vars;
|
|
std::unordered_map<ActionItem *, std::vector<size_t>> action_out_active_vars;
|
|
};
|
|
|
|
class CFGType {
|
|
public:
|
|
std::vector<std::shared_ptr<CFGNodeType>> nodes;
|
|
CFGNodeType *entry;
|
|
std::unordered_map<BlockItem *, CFGNodeType *> block_to_node;
|
|
std::unordered_map<std::string, BlockItem *> label_to_block;
|
|
std::vector<std::string> id_to_var;
|
|
std::unordered_map<std::string, size_t> var_to_id;
|
|
FunctionDefItem *corresponding_func;
|
|
void init() {
|
|
nodes.clear();
|
|
entry = nullptr;
|
|
block_to_node.clear();
|
|
label_to_block.clear();
|
|
id_to_var.clear();
|
|
var_to_id.clear();
|
|
corresponding_func = nullptr;
|
|
}
|
|
};
|
|
|
|
namespace opt {
|
|
class MoveInstruct : public ActionItem {
|
|
public:
|
|
std::string src_full;
|
|
std::string dest_full;
|
|
LLVMType ty;
|
|
MoveInstruct() = default;
|
|
void RecursivePrint([[maybe_unused]] std::ostream &os) const {
|
|
os << "[Persudo] " << dest_full << " <-- " << src_full << "\n";
|
|
}
|
|
};
|
|
} // namespace opt
|
|
|
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
|
Container GetCollectionsIntersection(const Container &a, const Container &b, Compare comp = Compare()) {
|
|
Container result;
|
|
auto ita = a.begin();
|
|
auto itb = b.begin();
|
|
|
|
while (ita != a.end() && itb != b.end()) {
|
|
if (comp(*ita, *itb)) {
|
|
++ita;
|
|
} else if (comp(*itb, *ita)) {
|
|
++itb;
|
|
} else {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
++itb;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
|
Container GetCollectionsUnion(const Container &a, const Container &b, Compare comp = Compare()) {
|
|
Container result;
|
|
auto ita = a.begin();
|
|
auto itb = b.begin();
|
|
|
|
while (ita != a.end() && itb != b.end()) {
|
|
if (comp(*ita, *itb)) {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
} else if (comp(*itb, *ita)) {
|
|
result.push_back(*itb);
|
|
++itb;
|
|
} else {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
++itb;
|
|
}
|
|
}
|
|
|
|
while (ita != a.end()) {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
}
|
|
|
|
while (itb != b.end()) {
|
|
result.push_back(*itb);
|
|
++itb;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
|
Container GetCollectionsDifference(const Container &a, const Container &b, Compare comp = Compare()) {
|
|
Container result;
|
|
auto ita = a.begin();
|
|
auto itb = b.begin();
|
|
|
|
while (ita != a.end() && itb != b.end()) {
|
|
if (comp(*ita, *itb)) {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
} else if (comp(*itb, *ita)) {
|
|
++itb;
|
|
} else {
|
|
++ita;
|
|
++itb;
|
|
}
|
|
}
|
|
|
|
while (ita != a.end()) {
|
|
result.push_back(*ita);
|
|
++ita;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
|
bool GetCollectionsIsSame(const Container &a, const Container &b, Compare comp = Compare()) {
|
|
auto ita = a.begin();
|
|
auto itb = b.begin();
|
|
|
|
while (ita != a.end() && itb != b.end()) {
|
|
if (comp(*ita, *itb) || comp(*itb, *ita)) {
|
|
return false;
|
|
}
|
|
++ita;
|
|
++itb;
|
|
}
|
|
|
|
return ita == a.end() && itb == b.end();
|
|
}
|
|
|
|
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func, bool remove_poison_entry = false);
|
|
|
|
// RISC-V calling convention compatible
|
|
const static std::vector<std::string> held_tmp_regs = {"x28", "x29", "x30", "x31"};
|
|
const static std::string zero = "x0", sp = "x2", ra = "x1", fp = "x8";
|
|
const static std::vector<std::string> callee_saved_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21",
|
|
"x22", "x23", "x24", "x25", "x26", "x27"};
|
|
const static std::vector<std::string> caller_saved_regs = {"x5", "x6", "x7", "x10", "x11", "x12",
|
|
"x13", "x14", "x15", "x16", "x17"};
|
|
const static std::vector<std::string> arg_regs = {"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
|
|
const static std::vector<std::string> allocating_regs = {"x3", "x4", "x9", "x18", "x19", "x20", "x21", "x22",
|
|
"x23", "x24", "x25", "x26", "x27", "x5", "x6", "x7",
|
|
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"};
|
|
|
|
inline bool VRegCheck(const std::string &s) {
|
|
if (s[0] != '%' && s[0] != '$' && s[0] != '#') return false;
|
|
return true;
|
|
} |