#pragma once #include "3rdparty/easylogging++.h" #include "common.h" #include "llir_type.h" #include #include #include #include #include #include #include #include namespace antlrSysY { 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 { ValuePtr_t 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; template static bool is(std::shared_ptr ptr) { if (ptr.get()) { // auto &r = *ptr.get(); // return typeid(r) == typeid(TT); return dynamic_cast(ptr.get()) != nullptr; } LOG(WARNING) << "Comparing with nullptr"; assert(0); return false; } // it is caller's duty to check before use `asType` template static std::shared_ptr as(std::shared_ptr ptr) { return std::dynamic_pointer_cast(ptr); } 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) {} void Add_Operand(ValuePtr_t op) { op->use_list.push_back({op, this, (unsigned)operand_list.size()}); operand_list.push_back(op); } // make anything that use this value use the new value void u_replace_users(ValuePtr_t value) { if (value == nullptr) { assert(!use_list.size() && "No one should use this"); return; } for (auto use : use_list) { auto user = use.user; auto index = use.op_index; user->operand_list[index] = value; assert(value); value->use_list.push_back({value, user, index}); } // all original uses are gone use_list.clear(); } // remove this user from its operands 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; BasicBlockListNode_t itr; std::list successors; std::list predecessors; 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 = parent; } }; 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) : Constant(name, TypeHelper::TYPE_I32), value(value) {} static std::shared_ptr make_shared(int value) { return std::make_shared("", value); } 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: 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)->element_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; } }; 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 antlrSysY