#pragma once #include "3rdparty/easylogging++.h" #include "common.h" #include "llir_type.h" #include #include #include #include #include #include #include #include namespace CompSysY { DEF_PTR_T(Value); DEF_PTR_T(BasicBlock); DEF_PTR_T(User); DEF_PTR_T(Function); DEF_PTR_T(Instruction); DEF_PTR_T(Constant); DEF_PTR_T(ConstantInt); // typedef std::tuple UseEdge_t; struct Use { // Value* value; User *user; unsigned op_index; }; // Define, User, operand-index // for Instruction, inst `uses` op, so inst is the user class Value { public: std::string name; TypePtr_t type; std::list use_list; // a list of use-edge from this value Value(const std::string &name, TypePtr_t type) : name(name), type(type) {} virtual ~Value() = default; virtual std::string to_string() { return name + ": " + type->to_string(); } virtual std::string to_IR_string() { panic("No applicable for IR gen"); } void u_remove_use(User *user) { // use_list.erase( // std::remove_if( // use_list.begin(), use_list.end(), [user](const UseEdge_t &use) { return std::get<1>(use) == user; } // ), // use_list.end() // ); for (auto itr = use_list.begin(); itr != use_list.end();) { if (itr->user == user) { itr = use_list.erase(itr); } else { ++itr; } } } }; class User : public Value { public: std::vector operand_list; User(const std::string &name, TypePtr_t type) : Value(name, type) {} /* 把一个Value加入到operands里面,同时维护use信息 */ void add_operand(ValuePtr_t op) { // value, use, op_index op->use_list.push_back({/*op.get(),*/ this, (unsigned)operand_list.size()}); operand_list.push_back(op); } /* 把所有this的use给换掉,然后this就没人用了 this拥有一个use_list,里面记录了所有使用this的指令 */ void u_replace_users(ValuePtr_t value) { for (auto use : use_list) { assert(value); use.user->operand_list[use.op_index] = value; value->use_list.push_back({/*value.get(),*/ use.user, use.op_index}); } // all original uses are gone use_list.clear(); } // 更新所有被use到的指令,因为this不再使用它,也就是从每个operands的use_list里面把自己删掉 void u_remove_from_usees() { for (auto op : operand_list) { assert(op); op->u_remove_use(this); } } }; class FParam : public Value { public: int ir_seqno = -1; FParam(const std::string &name, TypePtr_t type) : Value(name, type) {} virtual std::string to_string() override { return type->to_string() + " @" + name + " %" + std::to_string(ir_seqno); } virtual std::string to_IR_string() override { return type->to_IR_string() + " %" + std::to_string(ir_seqno); } }; typedef std::list>::iterator BasicBlockListNode_t; class Function : public Value { public: std::vector> fparam_list; std::list> bb_list; // we use empty basic_block to represent lib function Function(const std::string &name, TypePtr_t ret_type) : Value(name, std::make_shared(ret_type)) {} std::shared_ptr get_type() { return std::dynamic_pointer_cast(type); } bool is_libfunc() { return bb_list.size() == 0; } virtual std::string to_string() override { std::string params_str; for (auto fparam : fparam_list) { params_str += fparam->to_string() + ","; } return name + "(" + params_str + ") -> " + type->to_string(); } }; class BasicBlock : public Value { public: int ir_seqno = -1; std::list inst_list; std::shared_ptr parent_func; BasicBlockListNode_t itr; std::list succ_list; std::list pred_list; BasicBlockPtr_t IDOM; // dominating node std::unordered_set idom_set; // immediate dominated nodes std::unordered_set DOM_set; // dominated nodes std::unordered_set DF_set; int dom_level; int _dom_helper_index; int dom_dfs_in; int dom_dfs_out; BasicBlock(const std::string &name, std::shared_ptr parent) : Value(name, TypeHelper::TYPE_LABEL) { this->parent_func = parent; } static sptr(BasicBlock) New(const std::string &name, std::shared_ptr parent, const BasicBlockListNode_t &cur_bb_itr) { static int count = 0; auto basic_block = std::make_shared("blk" + std::to_string(count++), parent); basic_block->itr = parent->bb_list.insert(std::next(cur_bb_itr), basic_block); return basic_block; } }; class Constant : public Value { public: Constant(const std::string &name, TypePtr_t type) : Value(name, type) {} }; class ConstantInt : public Constant { public: int value; ConstantInt(const std::string &name, int value, TypePtr_t type) : Constant(name, type), value(value) {} static std::shared_ptr New(int value, TypePtr_t type = TypeHelper::TYPE_I32) { return std::make_shared("", value, type); } virtual std::string to_string() override { std::string str = type->to_string() + " " + std::to_string(value); return str; } virtual std::string to_IR_string() override { return type->to_IR_string() + " " + std::to_string(value); } }; class ConstantArr : public Constant { public: //! By default, this value_list is flattened and with size equal to declared size std::vector value_list; ConstantArr(const std::string &name, const std::vector &value_list, std::shared_ptr type) : Constant(name, type), value_list(value_list) { } int real_size() const { return std::dynamic_pointer_cast(type)->elem_count; } static std::shared_ptr make_shared( const std::string &name, const std::vector &value_list, std::shared_ptr type ) { return std::make_shared(name, value_list, type); } virtual std::string to_string() override { std::string str = "{"; for (auto elem : value_list) { if (elem) str += elem->to_string() + ", "; else str += "{...}, "; } if (real_size() > value_list.size()) { str += std::to_string(real_size() - value_list.size()) + " zeros"; } str += "}"; return str; } int get_memory_size() { return value_list.size() * 4; } }; typedef std::shared_ptr ConstantPtr_t; // emmm, actually it is more of a Instruction type class GlobalVar : public Value { public: ConstantPtr_t init_value; bool is_const; GlobalVar(const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const) : Value(name, PointerType::make_shared(type)), init_value(init_value), is_const(is_const) { } static std::shared_ptr make_shared( const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const ) { return std::make_shared(name, type, init_value, is_const); } virtual std::string to_IR_string() override { std::string str = type->to_IR_string() + " @" + name; return str; } }; std::shared_ptr gen_arr_hierarchy( const std::shared_ptr array_type, const std::vector &const_array, int base, int length ); } // namespace CompSysY