From 3b5cd82206bc5e7ee6a8886a3e489acb670f4df9 Mon Sep 17 00:00:00 2001 From: ridethepig Date: Thu, 15 Jun 2023 09:21:56 +0800 Subject: [PATCH] refine mem2reg, frontend refactor --- include/common.h | 1 + include/llir_instruction.h | 109 ++++++++++++++++++++++- include/llir_value.h | 35 +++----- include/visitor.h | 70 --------------- src/mc_codegen.cpp | 10 --- src/mc_inst.cpp | 2 +- src/pass_build_cfg.cpp | 16 ++-- src/pass_mem2reg.cpp | 153 +++++++++++++++----------------- src/pass_reg_alloc.cpp | 4 +- src/visitor.cpp | 176 ++++++++++++++++++------------------- src/visitor_factory.cpp | 155 -------------------------------- src/visitor_llir_gen.cpp | 164 +++++++++++++++++----------------- 12 files changed, 367 insertions(+), 528 deletions(-) delete mode 100644 src/visitor_factory.cpp diff --git a/include/common.h b/include/common.h index 81616c4..6b79f9e 100644 --- a/include/common.h +++ b/include/common.h @@ -36,6 +36,7 @@ inline sptr(DST) strict_shared_cast(SRC src) { #define STD_FIND(container, val) std::find(container.begin(), container.end(), val) #define STD_FOUND(container, val) (STD_FIND(container, val) != container.end()) #define INSET(cont, val) (cont.find(val) != cont.end()) +#define BEGINEND(cont) cont.begin(), cont.end() #define INF (0x3f3f3f3f) #define BTWN(v, l, r) (l <= v && v <= r) diff --git a/include/llir_instruction.h b/include/llir_instruction.h index 8365d29..6cc283c 100644 --- a/include/llir_instruction.h +++ b/include/llir_instruction.h @@ -52,7 +52,7 @@ public: int ir_seqno = -1; InstTag tag; BasicBlockPtr_t parent_bb; - decltype(BasicBlock::inst_list.begin()) inst_itr; + std::list::iterator inst_itr; Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb) : User("", type), tag(inst_tag), parent_bb(parent_bb) {} std::string tag_string() { @@ -98,6 +98,14 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static sptr(InstAlloca) New(const std::string &name, TypePtr_t type, sptr(BasicBlock) parent_bb) { + auto inst = std::make_shared(type, parent_bb); + inst->name = name; + auto func_head_bb = parent_bb->parent->bb_list.front(); + // put all alloca in the head of each basic block + inst->inst_itr = func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst); + return inst; + } }; class InstStore : public Instruction { @@ -108,6 +116,11 @@ public: Add_Operand(value); Add_Operand(pointer); } + static sptr(InstStore) New(sptr(Value) value, sptr(Value) pointer, sptr(BasicBlock) parent_bb) { + auto inst = std::make_shared(value, pointer, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; class InstLoad : public Instruction { @@ -120,6 +133,11 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static sptr(InstLoad) New(std::shared_ptr value, TypePtr_t type, std::shared_ptr parent_bb) { + auto inst = std::make_shared(value, type, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; class InstBinary : public Instruction { @@ -139,6 +157,34 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static sptr(InstBinary) New( + InstTag inst_tag, + std::shared_ptr op1, + std::shared_ptr op2, + std::shared_ptr parent_bb + ) { + std::shared_ptr inst; + if (InstTag::Lt <= inst_tag && inst_tag <= InstTag::Ne) { + inst = std::make_shared(inst_tag, TypeHelper::TYPE_I1, op1, op2, parent_bb); + } + else if (InstTag::Add <= inst_tag && inst_tag <= InstTag::Div) { + inst = std::make_shared(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb); + } + else { + panic("Invalid Binary Operation"); + } + assert(Type::isType(op1->type)); + assert(Type::isType(op2->type)); + if (!(Type::asType(op1->type)->int_type == Type::asType(op2->type)->int_type)) { + if (!(shared_cast(op1) && shared_cast(op1)->value == 0) + && !(shared_cast(op2) && shared_cast(op2)->value == 0)) { + LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string(); + assert(0); + } + } + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; // = zext to @@ -153,6 +199,11 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static sptr(InstZext) New(std::shared_ptr op, std::shared_ptr parent_bb) { + auto inst = std::make_shared(op, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; class InstBranch : public Instruction { @@ -164,11 +215,22 @@ public: this->Add_Operand(true_block); this->Add_Operand(false_block); } + static sptr(InstBranch) + New(ValuePtr_t cond, BasicBlockPtr_t true_block, BasicBlockPtr_t false_block, BasicBlockPtr_t parent_bb) { + auto inst = std::make_shared(cond, true_block, false_block, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } // unconditional branch InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) : Instruction(InstTag::Br, TypeHelper::TYPE_VOID, parent_bb) { this->Add_Operand(target_block); } + static sptr(InstBranch) New(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) { + auto inst = std::make_shared(target_block, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; class InstReturn : public Instruction { @@ -178,6 +240,16 @@ public: this->Add_Operand(ret_val); } InstReturn(BasicBlockPtr_t parent_bb) : Instruction(InstTag::Ret, TypeHelper::TYPE_VOID, parent_bb) {} + static sptr(InstReturn) New(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb) { + auto inst = std::make_shared(ret_val, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } + static sptr(InstReturn) New(BasicBlockPtr_t parent_bb) { + auto inst = std::make_shared(parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; // call's type is the function's return type @@ -197,6 +269,15 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static std::shared_ptr New( + FunctionPtr_t func, + const std::vector &args, + BasicBlockPtr_t parent_bb + ) { + auto inst = std::make_shared(func, args, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } }; // getelementptr , ptr {, [inrange] }* @@ -212,10 +293,10 @@ public: TypePtr_t element_type; InstGEP(ValuePtr_t pointer, const std::vector &indices, BasicBlockPtr_t parent_bb) : Instruction(InstTag::GEP, std::make_shared(extract_type(pointer, indices)), parent_bb) { - if (Value::is(pointer)) { + if (shared_cast(pointer)) { aim_to = std::dynamic_pointer_cast(pointer)->aim_to; } - else if (Value::is(pointer) || Value::is(pointer)) { + else if (shared_cast(pointer) || shared_cast(pointer)) { aim_to = pointer; } else { @@ -234,6 +315,15 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static std::shared_ptr New( + ValuePtr_t pointer, + const std::vector &indices, + BasicBlockPtr_t parent_bb + ) { + auto inst = std::make_shared(pointer, indices, parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); + return inst; + } // get the inner static TypePtr_t extract_type(ValuePtr_t pointer, const std::vector &indices) { @@ -261,7 +351,7 @@ public: void set_incoming_val(unsigned index, ValuePtr_t val) { auto old_op = operand_list[index]; operand_list[index] = val; - if (val) val->use_list.push_back({val, this, index}); + if (val) val->use_list.push_back({/*val.get(),*/ this, index}); if (old_op) { if (std::find(operand_list.begin(), operand_list.end(), old_op) == operand_list.end()) { old_op->u_remove_use(this); @@ -272,6 +362,17 @@ public: std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); return str; } + static InstPhiPtr_t New( + TypePtr_t type, + const decltype(Function::bb_list) &incoming_vals, + BasicBlockPtr_t parent_bb, + const std::string &name + ) { + auto inst = std::make_shared(type, incoming_vals, parent_bb); + inst->name = name; + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); + return inst; + } }; } // namespace CompSysY \ No newline at end of file diff --git a/include/llir_value.h b/include/llir_value.h index b07f786..c85af14 100644 --- a/include/llir_value.h +++ b/include/llir_value.h @@ -24,7 +24,7 @@ DEF_PTR_T(ConstantInt); // typedef std::tuple UseEdge_t; struct Use { - ValuePtr_t value; + // Value* value; User *user; unsigned op_index; }; @@ -40,24 +40,6 @@ public: 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(); } @@ -90,7 +72,8 @@ public: 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()}); + // value, use, op_index + op->use_list.push_back({/*op.get(),*/ this, (unsigned)operand_list.size()}); operand_list.push_back(op); } // make anything that use this value use the new value @@ -104,7 +87,7 @@ public: auto index = use.op_index; user->operand_list[index] = value; assert(value); - value->use_list.push_back({value, user, index}); + value->use_list.push_back({/*value.get(),*/ user, index}); } // all original uses are gone use_list.clear(); @@ -174,6 +157,14 @@ public: BasicBlock(const std::string &name, std::shared_ptr parent) : Value(name, TypeHelper::TYPE_LABEL) { this->parent = 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 { @@ -185,7 +176,7 @@ 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) { + static std::shared_ptr New(int value) { return std::make_shared("", value); } virtual std::string to_string() override { diff --git a/include/visitor.h b/include/visitor.h index c832491..f45f57b 100644 --- a/include/visitor.h +++ b/include/visitor.h @@ -20,76 +20,6 @@ namespace CompSysY { -#pragma region FactoryFunctionDeclaration -std::shared_ptr build_ConstantInt(const std::string &name, int value); - -std::shared_ptr build_BasicBlock( - const std::string &name, - std::shared_ptr parent, - const BasicBlockListNode_t &cur_bb_itr -); - -std::shared_ptr build_InstLoad( - std::shared_ptr value, - TypePtr_t type, - std::shared_ptr parent_bb -); - -std::shared_ptr build_InstStore( - std::shared_ptr value, - std::shared_ptr pointer, - std::shared_ptr parent_bb -); - -std::shared_ptr build_InstAlloca( - const std::string &str, - TypePtr_t type, - std::shared_ptr parent_bb -); - -std::shared_ptr build_InstBinary( - InstTag inst_tag, - std::shared_ptr op1, - std::shared_ptr op2, - std::shared_ptr parent_bb -); - -std::shared_ptr build_InstZext(std::shared_ptr op, std::shared_ptr parent_bb); - -std::shared_ptr build_InstBranch( - ValuePtr_t cond, - BasicBlockPtr_t true_block, - BasicBlockPtr_t false_block, - BasicBlockPtr_t parent_bb -); - -std::shared_ptr build_InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb); - -std::shared_ptr build_InstReturn(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb); - -std::shared_ptr build_InstReturn(BasicBlockPtr_t parent_bb); - -std::shared_ptr build_InstCall( - FunctionPtr_t func, - const std::vector &args, - BasicBlockPtr_t parent_bb -); - -std::shared_ptr build_InstGEP( - ValuePtr_t pointer, - const std::vector &indices, - BasicBlockPtr_t parent_bb -); - -InstPhiPtr_t build_InstPhi( - TypePtr_t type, - const decltype(Function::bb_list) &incoming_vals, - BasicBlockPtr_t parent_bb, - const std::string &name -); - -#pragma endregion - class Visitor : public SysyBaseVisitor { private: struct VisitorState { diff --git a/src/mc_codegen.cpp b/src/mc_codegen.cpp index 1cfe1e4..34d7298 100644 --- a/src/mc_codegen.cpp +++ b/src/mc_codegen.cpp @@ -79,16 +79,6 @@ static MOperand value2moperand( return vr; } else if (auto glob = shared_cast(ir_value)) { - // auto itr = val2mop.find(ir_value); - // if (itr != val2mop.end()) { - // return itr->second; - // } - // auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true); - // auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); - // val2mop.insert({ir_value, vr}); - // inst_symld->symbol = glob; - // inst_symld->dst = vr; - // return vr; auto op_glob = MOperand::Glob(glob); if (force_reg) { auto inst_la = MInstMove::New(mc_bb, InsertPos::Tail); diff --git a/src/mc_inst.cpp b/src/mc_inst.cpp index 8709020..45ed570 100644 --- a/src/mc_inst.cpp +++ b/src/mc_inst.cpp @@ -147,7 +147,7 @@ std::vector MInstCall::get_use() const { #pragma endregion void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_ty) { - inst->inst_tag = tag; + inst->inst_tag = tag; inst->parent_bb = parent_bb; switch (ins_ty) { case InsertPos::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break; diff --git a/src/pass_build_cfg.cpp b/src/pass_build_cfg.cpp index 2c3f420..1006a0e 100644 --- a/src/pass_build_cfg.cpp +++ b/src/pass_build_cfg.cpp @@ -41,13 +41,13 @@ static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) { static void _build_cfg(const FunctionPtr_t func) { for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) { auto bb = *itr; - if (bb->inst_list.size() == 1 && Value::is(bb->inst_list.front())) { - auto br = Value::as(bb->inst_list.front()); + if (bb->inst_list.size() == 1 && shared_cast(bb->inst_list.front())) { + auto br = shared_cast(bb->inst_list.front()); if (br->operand_list.size() == 1) { VLOG(6) << "remove dummy jump block:" << bb->name; for (auto &use : bb->use_list) { use.user->operand_list[use.op_index] = br->operand_list[0]; - br->operand_list[0]->use_list.push_back({br->operand_list[0], use.user, use.op_index}); + br->operand_list[0]->use_list.push_back({/*br->operand_list[0],*/ use.user, use.op_index}); } itr = func->bb_list.erase(itr); continue; @@ -57,14 +57,14 @@ static void _build_cfg(const FunctionPtr_t func) { } for (auto basicblock : func->bb_list) { auto _inst_br = basicblock->inst_list.back(); - if (!Value::is(_inst_br)) continue; - auto inst_br = Value::as(_inst_br); + if (!shared_cast(_inst_br)) continue; + auto inst_br = shared_cast(_inst_br); if (inst_br->operand_list.size() == 1) { - connect(basicblock, Value::as(inst_br->operand_list[0])); + connect(basicblock, shared_cast(inst_br->operand_list[0])); } else if (inst_br->operand_list.size() == 3) { - connect(basicblock, Value::as(inst_br->operand_list[1])); - connect(basicblock, Value::as(inst_br->operand_list[2])); + connect(basicblock, shared_cast(inst_br->operand_list[1])); + connect(basicblock, shared_cast(inst_br->operand_list[2])); } else { panic("br should have either 1 or 3 operands"); diff --git a/src/pass_mem2reg.cpp b/src/pass_mem2reg.cpp index 914bc8d..4ff0f53 100644 --- a/src/pass_mem2reg.cpp +++ b/src/pass_mem2reg.cpp @@ -14,53 +14,40 @@ namespace CompSysY { struct AllocaInfo { std::vector def_blocks = {}; std::vector use_blocks = {}; - bool only_in_1_block = true; - BasicBlockPtr_t only_block = nullptr; - InstStore *only_store = nullptr; }; -static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) { +static void analyze_alloca_defuse(InstAllocaPtr_t ai, AllocaInfo &info) { for (auto use : ai->use_list) { auto user = dynamic_cast(use.user); if (dynamic_cast(user)) { const auto si = dynamic_cast(user); info.def_blocks.push_back(si->parent_bb); - info.only_store = si; } else { assert(dynamic_cast(user)); const auto li = dynamic_cast(user); info.use_blocks.push_back(li->parent_bb); } - if (info.only_in_1_block) { - if (!info.only_block) - info.only_block = user->parent_bb; - else if (info.only_block != user->parent_bb) - info.only_in_1_block = false; - } - } - if (VLOG_IS_ON(6)) { - std::cout << "Alloca " << ai->name; - std::cout << " Def: ["; - for (auto blk : info.def_blocks) { - std::cout << blk->name << ", "; - } - std::cout << "]\n"; - std::cout << " Use: ["; - for (auto blk : info.use_blocks) { - std::cout << blk->name << ", "; - } - std::cout << "]\n"; - std::cout.flush(); } } -// static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) { - -// } +static void print_alloca_defuse(InstAllocaPtr_t ai, const AllocaInfo &info) { + std::cout << "Alloca " << ai->name; + std::cout << " Def: ["; + for (auto blk : info.def_blocks) { + std::cout << blk->name << ", "; + } + std::cout << "]\n"; + std::cout << " Use: ["; + for (auto blk : info.use_blocks) { + std::cout << blk->name << ", "; + } + std::cout << "]\n"; + std::cout.flush(); +} // live in analysis -static void live_in_blocks( +static void analyze_alloca_livein( InstAllocaPtr_t ai, AllocaInfo &alloca_info, const std::unordered_set &def_blocks, @@ -74,15 +61,15 @@ static void live_in_blocks( if (def_blocks.count(bb) == 0) continue; for (auto itr : bb->inst_list) { // a store to this alloca(variable) before a load, it is dead in this block - if (Value::is(itr) && Value::as(itr)->operand_list[1] == ai) { + if (shared_cast(itr) && shared_cast(itr)->operand_list[1] == ai) { worklist[i] = worklist.back(); worklist.pop_back(); --i; break; } - else if (Value::is(itr)) { + else if (shared_cast(itr)) { // a load before store, it live in this block - if (Value::as(itr)->operand_list[0] == ai) break; + if (shared_cast(itr)->operand_list[0] == ai) break; } } } @@ -101,6 +88,15 @@ static void live_in_blocks( } } +static void print_alloca_livein(InstAllocaPtr_t ai, const std::unordered_set &livein_blocks) { + std::cout << "Live-in blocks of " << ai->name << ": ["; + for (auto livein : livein_blocks) { + std::cout << livein->name << ", "; + } + std::cout << "]\n"; + std::cout.flush(); +} + struct RenameInfo { BasicBlockPtr_t bb; BasicBlockPtr_t pred; @@ -155,8 +151,8 @@ static void print_dom_tree(BasicBlockPtr_t rt) { // https://roife.github.io/2022/02/07/mem2reg/ // https://github.com/Enna1/LLVM-Study-Notes/blob/master/source/ssa/SSA-Construction.rst static void _mem_2_reg(FunctionPtr_t func) { - VLOG(4) << "Run mem2reg for " << func->name; - VLOG(4) << " Gen Dominance Tree & Frontier"; + LOG(TRACE) << "Run mem2reg for " << func->name; + VLOG(6) << "[mem2reg] Gen Dominance Tree & Frontier"; gen_dominance(func); gen_dominance_frontier(func); if (VLOG_IS_ON(6)) print_dom_tree(func->bb_list.front()); @@ -170,18 +166,22 @@ static void _mem_2_reg(FunctionPtr_t func) { for (auto bb : func->bb_list) { for (auto inst : bb->inst_list) { - if (Value::is(inst)) { + if (shared_cast(inst)) { // assert(inst->parent_bb == bb); // 貌似没问题,parent_bb是插入alloca的时候的那个block,而alloca实际上是被插入在entry_block的 assert(bb == func->bb_list.front() && "Alloca should be at front of a func"); - auto ai = Value::as(inst); - // assert(is_alloca_promotable(ai) && "Invalid alloca"); + auto ai = shared_cast(inst); + // 暂时只考虑int类型的alloca, 数组和指针都先不管 if (!Type::isType(get_pointed_type(ai->type))) continue; alloca_list.push_back(ai); } } } - VLOG(4) << " alloca pruning & phi insertion"; + int id = 0; + for (auto bb : func->bb_list) { + bb_to_id[bb] = id++; + } + VLOG(6) << "[mem2reg] Alloca pruning & phi insertion"; for (unsigned i = 0; i != alloca_list.size(); ++i) { auto ai = alloca_list[i]; // remove empty use @@ -192,36 +192,23 @@ static void _mem_2_reg(FunctionPtr_t func) { --i; continue; } + // analyze alloca's def&use AllocaInfo alloca_info; - analyze_alloca(ai, alloca_info); - if (alloca_info.def_blocks.size() == 1) { - LOG(WARNING) << "To rewrite single store"; - } - if (alloca_info.only_in_1_block) { - LOG(WARNING) << "To promote single block alloca"; - } - // numbering bb - if (bb_to_id.empty()) { - int id = 0; - for (auto bb : func->bb_list) { - bb_to_id[bb] = id++; - } + analyze_alloca_defuse(ai, alloca_info); + if (VLOG_IS_ON(6)) { + print_alloca_defuse(ai, alloca_info); } alloca_to_id[alloca_list[i]] = i; - std::unordered_set def_blocks(alloca_info.def_blocks.begin(), alloca_info.def_blocks.end()); + // compute alloca's livein blocks + std::unordered_set def_blocks(BEGINEND(alloca_info.def_blocks)); std::unordered_set livein_blocks; - live_in_blocks(ai, alloca_info, def_blocks, livein_blocks); + analyze_alloca_livein(ai, alloca_info, def_blocks, livein_blocks); if (VLOG_IS_ON(6)) { - std::cout << "Live-in blocks of " << ai->name << ": ["; - for (auto livein : livein_blocks) { - std::cout << livein->name << ", "; - } - std::cout << "]\n"; - std::cout.flush(); + print_alloca_livein(ai, livein_blocks); } - // llvm use IDF to calculate phi blocks. - // But that is too complicated - // SSA book Algo 3.1 + // llvm use IDF to calculate phi blocks. But that is too complicated + // SSA book Algo 3.1, with non-livein blocks skipped + // 算法本质上是对于该alloca的每个def块,在对应的支配边界上放置phi(如果放过就不放了),同时如果alloca没有在DF中用到,也会跳过 std::vector visited(func->bb_list.size(), false); for (auto bb : def_blocks) { worklist.push(bb); @@ -230,15 +217,13 @@ static void _mem_2_reg(FunctionPtr_t func) { auto bb = worklist.front(); worklist.pop(); for (auto frontier : bb->DF_set) { - // LOG(DEBUG) << "visiting " << bb->name <<" : " << frontier->name; auto frontier_index = bb_to_id.at(frontier); if (!visited[frontier_index]) { visited[frontier_index] = true; - // livein-block opt is workable in IDF, but not here - // if (livein_blocks.count(frontier)) { - auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->pred_list, frontier, ai->name); - phi_to_allocaid.insert({inst_phi, i}); - // } + if (livein_blocks.count(frontier)) { + auto inst_phi = InstPhi::New(TypeHelper::TYPE_I32, frontier->pred_list, frontier, ai->name); + phi_to_allocaid.insert({inst_phi, i}); + } if (!def_blocks.count(frontier)) { worklist.push(frontier); } @@ -247,10 +232,10 @@ static void _mem_2_reg(FunctionPtr_t func) { } } if (alloca_list.empty()) return; - // renaming - VLOG(4) << " variable renaming"; + + VLOG(6) << "[mem2reg] Variable renaming"; std::vector _init_values; - for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::make_shared(0)); + for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::New(0)); std::vector rename_list = {{func->bb_list.front(), nullptr, _init_values}}; std::vector visited(bb_to_id.size(), 0); while (!rename_list.empty()) { @@ -259,8 +244,8 @@ static void _mem_2_reg(FunctionPtr_t func) { // replace block with more specific alloca for (auto inst : rename_info.bb->inst_list) { // phi only appear at block head - if (!Value::is(inst)) break; - auto phi = Value::as(inst); + if (!shared_cast(inst)) break; + auto phi = shared_cast(inst); auto alloca_index = phi_to_allocaid.at(phi); int pred_index = -1; for (auto pred : rename_info.bb->pred_list) { @@ -276,15 +261,15 @@ static void _mem_2_reg(FunctionPtr_t func) { for (auto itr = rename_info.bb->inst_list.begin(); itr != rename_info.bb->inst_list.end();) { auto inst = *itr++; // we skip non-integer alloca, they are not in our alloca_list - if (Value::is(inst) && alloca_to_id.count(Value::as(inst))) { + if (shared_cast(inst) && alloca_to_id.count(shared_cast(inst))) { rename_info.bb->inst_list.remove(inst); } - else if (Value::is(inst)) { - auto li = Value::as(inst); - if (!(Value::is(li->operand_list[0]))) { + else if (shared_cast(inst)) { + auto li = shared_cast(inst); + if (!(shared_cast(li->operand_list[0]))) { continue; } - auto ai = Value::as(li->operand_list[0]); + auto ai = shared_cast(li->operand_list[0]); if (!Type::isType(get_pointed_type(ai->type))) { continue; } @@ -293,12 +278,12 @@ static void _mem_2_reg(FunctionPtr_t func) { li->u_replace_users(rename_info.value_list[alloca_index]); inst->u_remove_from_usees(); } - else if (Value::is(inst)) { - auto si = Value::as(inst); - if (!(Value::is(si->operand_list[1]))) { + else if (shared_cast(inst)) { + auto si = shared_cast(inst); + if (!(shared_cast(si->operand_list[1]))) { continue; } - auto ai = Value::as(si->operand_list[1]); + auto ai = shared_cast(si->operand_list[1]); if (!Type::isType(get_pointed_type(ai->type))) { continue; } @@ -309,8 +294,8 @@ static void _mem_2_reg(FunctionPtr_t func) { si->u_replace_users(nullptr); rename_info.bb->inst_list.remove(inst); } - else if (Value::is(inst)) { - auto phi = Value::as(inst); + else if (shared_cast(inst)) { + auto phi = shared_cast(inst); int alloca_index = phi_to_allocaid.at(phi); rename_info.value_list[alloca_index] = phi; } diff --git a/src/pass_reg_alloc.cpp b/src/pass_reg_alloc.cpp index a9ffc51..a5523e9 100644 --- a/src/pass_reg_alloc.cpp +++ b/src/pass_reg_alloc.cpp @@ -490,7 +490,7 @@ if !spilledNodes.empty() then void PassRegAlloc::apply_coalesced(MFunction *func) { for (auto bb : func->bb_list) { - for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end(); ) { + for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end();) { auto inst = *itr; auto defs = inst->get_def_ptr(); auto uses = inst->get_use_ptr(); @@ -508,7 +508,7 @@ void PassRegAlloc::apply_coalesced(MFunction *func) { continue; } } - ++ itr; + ++itr; } } } diff --git a/src/visitor.cpp b/src/visitor.cpp index 896aa66..4eaccd8 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -195,11 +195,11 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) { } // local variable else { - auto alloca_ = build_InstAlloca(var_name, TypeHelper::TYPE_I32, _state.current_bb); + auto alloca_ = InstAlloca::New(var_name, TypeHelper::TYPE_I32, _state.current_bb); _scope_tab.push_name(var_name, alloca_); if (ctx->initVal()) { auto init_val = any_to_Value(visitInitVal(ctx->initVal())); - build_InstStore(init_val, alloca_, _state.current_bb); + InstStore::New(init_val, alloca_, _state.current_bb); } } } @@ -214,7 +214,7 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) { auto array_type = ArrayType::build_from_list(dim_list); // local array if (_scope_tab.get_level()) { - auto alloca_ = build_InstAlloca(var_name, array_type, _state.current_bb); + auto alloca_ = InstAlloca::New(var_name, array_type, _state.current_bb); _scope_tab.push_name(var_name, alloca_); if (ctx->initVal()) { _state.arr_dim_index = 0; @@ -223,21 +223,21 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) { _state.arr_dim_list = nullptr; sysy_assert(_state.arr_dim_index == 0); // Build GEP - auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb); + auto base_ptr = InstGEP::New(alloca_, {CONST0, CONST0}, _state.current_bb); for (int i = 1; i < dim_list.size(); ++i) { - base_ptr = build_InstGEP(base_ptr, {CONST0, CONST0}, _state.current_bb); + base_ptr = InstGEP::New(base_ptr, {CONST0, CONST0}, _state.current_bb); } - auto inst_call = build_InstCall( + auto inst_call = InstCall::New( _func_tab.get_name("memset").value(), - {base_ptr, CONST0, ConstantInt::make_shared(array_value.size() * 4)}, + {base_ptr, CONST0, ConstantInt::New(array_value.size() * 4)}, _state.current_bb ); // TODO: BAAU-2021 calls memset in `libc` (not sysylib) to optimize this process - if (array_value[0]) build_InstStore(array_value[0], base_ptr, _state.current_bb); + if (array_value[0]) InstStore::New(array_value[0], base_ptr, _state.current_bb); for (int i = 1; i < array_value.size(); ++i) { if (!array_value[i]) continue; - auto ptr = build_InstGEP(base_ptr, {ConstantInt::make_shared(i)}, _state.current_bb); - build_InstStore(array_value[i], ptr, _state.current_bb); + auto ptr = InstGEP::New(base_ptr, {ConstantInt::New(i)}, _state.current_bb); + InstStore::New(array_value[i], ptr, _state.current_bb); } } // If there is no init expr, let it be @@ -287,7 +287,7 @@ std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) { for (auto init_val : ctx->initVal()) { if (init_val->exp()) { auto exp_value = any_to_Value(visitInitVal(init_val)); - if (_state.isGlobalIint) assert(Value::is(exp_value)); + if (_state.isGlobalIint) assert(shared_cast(exp_value)); cur_arr.push_back(exp_value); } else { @@ -385,16 +385,16 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) { auto add_exp = any_to_Value(visitAddExp(ctx->addExp())); auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp())); if (std::dynamic_pointer_cast(add_exp->type)->isI1()) { - add_exp = build_InstZext(add_exp, _state.current_bb); + add_exp = InstZext::New(add_exp, _state.current_bb); } if (std::dynamic_pointer_cast(mul_exp->type)->isI1()) { - mul_exp = build_InstZext(mul_exp, _state.current_bb); + mul_exp = InstZext::New(mul_exp, _state.current_bb); } if (ctx->ADD()) { - mul_exp = build_InstBinary(InstTag::Add, add_exp, mul_exp, _state.current_bb); + mul_exp = InstBinary::New(InstTag::Add, add_exp, mul_exp, _state.current_bb); } else if (ctx->SUB()) { - mul_exp = build_InstBinary(InstTag::Sub, add_exp, mul_exp, _state.current_bb); + mul_exp = InstBinary::New(InstTag::Sub, add_exp, mul_exp, _state.current_bb); } else panic("Unreachable"); @@ -430,19 +430,19 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) { auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp())); auto unary_exp = any_to_Value(visitUnaryExp(ctx->unaryExp())); if (std::dynamic_pointer_cast(unary_exp->type)->isI1()) { - unary_exp = build_InstZext(unary_exp, _state.current_bb); + unary_exp = InstZext::New(unary_exp, _state.current_bb); } if (std::dynamic_pointer_cast(mul_exp->type)->isI1()) { - mul_exp = build_InstZext(mul_exp, _state.current_bb); + mul_exp = InstZext::New(mul_exp, _state.current_bb); } if (ctx->MUL()) { - unary_exp = build_InstBinary(InstTag::Mul, mul_exp, unary_exp, _state.current_bb); + unary_exp = InstBinary::New(InstTag::Mul, mul_exp, unary_exp, _state.current_bb); } else if (ctx->DIV()) { - unary_exp = build_InstBinary(InstTag::Div, mul_exp, unary_exp, _state.current_bb); + unary_exp = InstBinary::New(InstTag::Div, mul_exp, unary_exp, _state.current_bb); } else if (ctx->MOD()) { - unary_exp = build_InstBinary(InstTag::Mod, mul_exp, unary_exp, _state.current_bb); + unary_exp = InstBinary::New(InstTag::Mod, mul_exp, unary_exp, _state.current_bb); } else panic("Unreachable"); @@ -460,16 +460,16 @@ std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) { auto add_exp = any_to_Value(visitAddExp(ctx->addExp())); sysy_assert(IntegerType::isIntegerTypeI32(rel_exp->type)); if (ctx->LE()) { - add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb); + add_exp = InstBinary::New(InstTag::Le, rel_exp, add_exp, _state.current_bb); } else if (ctx->LT()) { - add_exp = build_InstBinary(InstTag::Lt, rel_exp, add_exp, _state.current_bb); + add_exp = InstBinary::New(InstTag::Lt, rel_exp, add_exp, _state.current_bb); } else if (ctx->GE()) { - add_exp = build_InstBinary(InstTag::Ge, rel_exp, add_exp, _state.current_bb); + add_exp = InstBinary::New(InstTag::Ge, rel_exp, add_exp, _state.current_bb); } else if (ctx->GT()) { - add_exp = build_InstBinary(InstTag::Gt, rel_exp, add_exp, _state.current_bb); + add_exp = InstBinary::New(InstTag::Gt, rel_exp, add_exp, _state.current_bb); } else { LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText(); @@ -492,16 +492,16 @@ std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) { need_zext = true; } if (need_zext && IntegerType::isIntegerTypeI1(eq_exp->type)) { - eq_exp = build_InstZext(eq_exp, _state.current_bb); + eq_exp = InstZext::New(eq_exp, _state.current_bb); } if (need_zext && IntegerType::isIntegerTypeI1(rel_exp->type)) { - rel_exp = build_InstZext(rel_exp, _state.current_bb); + rel_exp = InstZext::New(rel_exp, _state.current_bb); } if (ctx->EQ()) { - rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb); + rel_exp = InstBinary::New(InstTag::Eq, eq_exp, rel_exp, _state.current_bb); } else if (ctx->NE()) { - rel_exp = build_InstBinary(InstTag::Ne, eq_exp, rel_exp, _state.current_bb); + rel_exp = InstBinary::New(InstTag::Ne, eq_exp, rel_exp, _state.current_bb); } else panic("Unreachable"); @@ -521,15 +521,15 @@ std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) { std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) { auto eq_exp_list = ctx->eqExp(); for (int i = 0; i < eq_exp_list.size(); ++i) { - auto next_block = build_BasicBlock("", _state.current_func, _state.current_bb->itr); + auto next_block = BasicBlock::New("", _state.current_func, _state.current_bb->itr); auto eq_exp = any_to_Value(visitEqExp(eq_exp_list[i])); auto condition = eq_exp; if (!IntegerType::isIntegerTypeI1(eq_exp->type)) - condition = build_InstBinary(InstTag::Ne, eq_exp, CONST0, _state.current_bb); - build_InstBranch(condition, next_block, ctx->false_block, _state.current_bb); + condition = InstBinary::New(InstTag::Ne, eq_exp, CONST0, _state.current_bb); + InstBranch::New(condition, next_block, ctx->false_block, _state.current_bb); _state.current_bb = next_block; } - build_InstBranch(ctx->true_block, _state.current_bb); + InstBranch::New(ctx->true_block, _state.current_bb); return {}; } @@ -540,7 +540,7 @@ std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) { auto and_exp_list = ctx->lAndExp(); auto n_and_exp = and_exp_list.size(); for (int i = 0; i < n_and_exp - 1; ++i) { - auto next_block = build_BasicBlock("", _state.current_func, _state.current_bb->itr); + auto next_block = BasicBlock::New("", _state.current_func, _state.current_bb->itr); ctx->lAndExp(i)->true_block = ctx->true_block; ctx->lAndExp(i)->false_block = next_block; visitLAndExp(and_exp_list[i]); @@ -588,18 +588,18 @@ std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) { auto unary_exp = any_to_Value(_result); sysy_assert(unary_exp->type->type_tag == Type::TypeTag::IntegerType); if (std::dynamic_pointer_cast(unary_exp->type)->isI1()) { - unary_exp = build_InstZext(unary_exp, _state.current_bb); + unary_exp = InstZext::New(unary_exp, _state.current_bb); } if (ctx->unaryOp()->NOT()) { // should eval to i1 sysy_assert(_state.isCondExp); - return build_InstBinary(InstTag::Eq, unary_exp, CONST0, _state.current_bb); + return InstBinary::New(InstTag::Eq, unary_exp, CONST0, _state.current_bb); } else if (ctx->unaryOp()->ADD()) { return unary_exp; } else if (ctx->unaryOp()->SUB()) { - return build_InstBinary(InstTag::Sub, CONST0, unary_exp, _state.current_bb); + return InstBinary::New(InstTag::Sub, CONST0, unary_exp, _state.current_bb); } } else if (ctx->IDENT()) { @@ -625,7 +625,7 @@ std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) { args.push_back(exp); } } - return build_InstCall(func, args, _state.current_bb); + return InstCall::New(func, args, _state.current_bb); } else if (ctx->primaryExp()) { return visitPrimaryExp(ctx->primaryExp()); @@ -675,7 +675,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) { // LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag; // should be InstAlloca auto ptr_type = std::dynamic_pointer_cast(lval->type); - return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb); + return InstLoad::New(lval, ptr_type->pointed_type, _state.current_bb); } } } @@ -704,7 +704,7 @@ std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) { else if (ctx->OCTAL_CONST()) { const_int = std::stol(ctx->OCTAL_CONST()->getText(), nullptr, 8); } - return build_ConstantInt("", const_int); + return ConstantInt::New(const_int); } // lVal: IDENT ('[' exp ']')*; @@ -737,7 +737,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto gep = lval; for (auto exp_ctx : ctx->exp()) { auto exp = any_to_Value(visitExp(exp_ctx)); - gep = build_InstGEP(gep, {exp}, _state.current_bb); + gep = InstGEP::New(gep, {exp}, _state.current_bb); } return gep; } @@ -748,22 +748,22 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { // @retval: InstLoad LOG(WARNING) << "Unexpected pointer"; auto pointed_type = std::dynamic_pointer_cast(lval->type)->pointed_type; - auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); + auto inst_load = InstLoad::New(lval, pointed_type, _state.current_bb); return inst_load; } else { // fparam array, whose first dim is represented by a pointer #if 0 auto pointed_type = Type::asType(lval->type)->pointed_type; - auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); + auto inst_load = InstLoad::New(lval, pointed_type, _state.current_bb); auto exp_list = ctx->exp(); if (exp_list.size() == 1) { auto exp_val = any_to_Value(visitExp(exp_list[0])); - auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb); + auto ptr = InstGEP::New(inst_load, {exp_val}, _state.current_bb); pointed_type = Type::asType(ptr->type)->pointed_type; return ptr; } - auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb); + auto ptr = InstGEP::New(inst_load, {CONST0}, _state.current_bb); pointed_type = Type::asType(ptr->type)->pointed_type; ValuePtr_t offset = ConstantInt::make_shared(0); assert(Type::isType(pointed_type)); @@ -774,42 +774,42 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto array_type = std::dynamic_pointer_cast(pointed_type); auto exp_val = any_to_Value(visitExp(exp_list[i])); auto dim_size = ConstantInt::make_shared(array_type->element_count); - auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb); - auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb); + auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb); + auto inst_mul = InstBinary::New(InstTag::Mul, inst_add, dim_size, _state.current_bb); offset = inst_mul; pointed_type = array_type->element_type; - ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb); } // visit the last dimension, mul is not needed auto exp_val = any_to_Value(visitExp(exp_list.back())); - auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb); + auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb); offset = inst_add; // finally, we get the offset pointed_type = std::dynamic_pointer_cast(ptr->type)->pointed_type; if (shared_cast(pointed_type)) { // return the address of the array element - auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb); + auto arr_elem_ptr = InstGEP::New(ptr, {offset}, _state.current_bb); return arr_elem_ptr; } else { LOG(WARNING) << "Should be int"; - auto arr_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb); + auto arr_ptr = InstGEP::New(ptr, {CONST0, offset}, _state.current_bb); return arr_ptr; } #else // for array type in fparam, say a[][5][4], the type looks like: // alloca->pointer->array[5x4]->array[4] auto exp_list = ctx->exp(); - auto inst_load = build_InstLoad(lval, lval_pointed_type, _state.current_bb); + auto inst_load = InstLoad::New(lval, lval_pointed_type, _state.current_bb); ValuePtr_t ptr = inst_load; auto exp_val = any_to_Value(visitExp(exp_list.front())); - ptr = build_InstGEP(ptr, {exp_val}, _state.current_bb); + ptr = InstGEP::New(ptr, {exp_val}, _state.current_bb); for (int i = 1; i < exp_list.size(); ++i) { auto exp_val = any_to_Value(visitExp(exp_list[i])); - ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, exp_val}, _state.current_bb); } if (Type::isType(get_pointed_type(ptr->type))) { - ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb); } return ptr; #endif @@ -819,7 +819,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { // get &array[0] #if 0 auto exp_list = ctx->exp(); - auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb); + auto ptr = InstGEP::New(lval, {CONST0, CONST0}, _state.current_bb); auto pointed_type = std::dynamic_pointer_cast(ptr->type)->pointed_type; ValuePtr_t offset = ConstantInt::make_shared(0); // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] @@ -828,27 +828,27 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto array_type = std::dynamic_pointer_cast(pointed_type); auto exp_val = any_to_Value(visitExp(exp_list[i])); auto dim_size = ConstantInt::make_shared(array_type->element_count); - auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb); - auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb); + auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb); + auto inst_mul = InstBinary::New(InstTag::Mul, inst_add, dim_size, _state.current_bb); offset = inst_mul; pointed_type = array_type->element_type; - ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb); } auto exp_val = any_to_Value(visitExp(exp_list.back())); - auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb); + auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb); offset = inst_add; // finally, we get the offset pointed_type = std::dynamic_pointer_cast(ptr->type)->pointed_type; if (shared_cast(pointed_type)) { // return the address of the array element - auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb); + auto arr_elem_ptr = InstGEP::New(ptr, {offset}, _state.current_bb); return arr_elem_ptr; } else { // return the address of an sub array auto array_type = std::dynamic_pointer_cast(pointed_type); auto dim_size = ConstantInt::make_shared(array_type->element_count); - offset = build_InstBinary(InstTag::Mul, offset, dim_size, _state.current_bb); - auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb); + offset = InstBinary::New(InstTag::Mul, offset, dim_size, _state.current_bb); + auto arr_elem_ptr = InstGEP::New(ptr, {CONST0, offset}, _state.current_bb); return arr_elem_ptr; } #else @@ -856,10 +856,10 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { ValuePtr_t ptr = lval; for (int i = 0; i < exp_list.size(); ++i) { auto exp_val = any_to_Value(visitExp(exp_list[i])); - ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, exp_val}, _state.current_bb); } if (Type::isType(get_pointed_type(ptr->type))) { - ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb); } return ptr; #endif @@ -881,7 +881,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) { auto func_obj = std::make_shared(func_name, func_ret_type); module.function_list.push_back(func_obj); _func_tab.push_name(func_name, func_obj); - auto basic_block = build_BasicBlock(func_name + "_ENTRY", func_obj, func_obj->bb_list.begin()); + auto basic_block = BasicBlock::New(func_name + "_ENTRY", func_obj, func_obj->bb_list.begin()); _scope_tab.enter_scope(true); _state.current_func = func_obj; _state.current_bb = basic_block; @@ -898,12 +898,12 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) { if (func_obj->bb_list.back()->inst_list.size() == 0 && func_obj->bb_list.back()->name == "after_ret") { func_obj->bb_list.pop_back(); } - if (func_obj->bb_list.back()->inst_list.size() == 0 || !Value::is(func_obj->bb_list.back()->inst_list.back())) { + if (func_obj->bb_list.back()->inst_list.size() == 0 || !shared_cast(func_obj->bb_list.back()->inst_list.back())) { if (func_ret_type->type_tag == Type::TypeTag::VoidType) { - build_InstReturn(_state.current_bb); + InstReturn::New(_state.current_bb); } else { - build_InstReturn(CONST0, _state.current_bb); + InstReturn::New(CONST0, _state.current_bb); } } return {}; @@ -916,8 +916,8 @@ std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) { auto fparam_type = any_to_Type(visitFuncFParam(fparam_ctx)); auto fparam_name = fparam_ctx->IDENT()->getText(); auto fparam = std::make_shared(fparam_name, fparam_type); - auto alloca_ = build_InstAlloca(fparam_name, fparam_type, _state.current_bb); - build_InstStore(fparam, alloca_, _state.current_bb); + auto alloca_ = InstAlloca::New(fparam_name, fparam_type, _state.current_bb); + InstStore::New(fparam, alloca_, _state.current_bb); _scope_tab.push_name(fparam_name, alloca_); _state.current_func->fparam_list.push_back(fparam); } @@ -973,7 +973,7 @@ stmt: lVal '=' exp ';' # assignStmt std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) { auto lval = any_to_Value(visitLVal(ctx->lVal())); auto rhs = any_to_Value(visitExp(ctx->exp())); - auto store = build_InstStore(rhs, lval, _state.current_bb); + auto store = InstStore::New(rhs, lval, _state.current_bb); return {}; } @@ -981,11 +981,11 @@ std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) { std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) { VLOG(5) << "Visiting IfStmt " << "; lineno=" << ctx->getStart()->getLine(); - auto true_block = build_BasicBlock("_then", _state.current_func, _state.current_bb->itr); - auto next_block = build_BasicBlock("_next", _state.current_func, true_block->itr); + auto true_block = BasicBlock::New("_then", _state.current_func, _state.current_bb->itr); + auto next_block = BasicBlock::New("_next", _state.current_func, true_block->itr); auto false_block = next_block; if (ctx->ELSE()) { - false_block = build_BasicBlock("_else", _state.current_func, true_block->itr); + false_block = BasicBlock::New("_else", _state.current_func, true_block->itr); } ctx->cond()->lOrExp()->true_block = true_block; ctx->cond()->lOrExp()->false_block = false_block; @@ -993,11 +993,11 @@ std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) { _state.current_bb = true_block; visit(ctx->stmt(0)); - build_InstBranch(next_block, _state.current_bb); // use current_bb, god knows what happened + InstBranch::New(next_block, _state.current_bb); // use current_bb, god knows what happened if (ctx->ELSE()) { _state.current_bb = false_block; visit(ctx->stmt(1)); - build_InstBranch(next_block, _state.current_bb); + InstBranch::New(next_block, _state.current_bb); } _state.current_bb = next_block; return {}; @@ -1008,10 +1008,10 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) { VLOG(5) << "Visiting WhileStmt " << "; lineno=" << ctx->getStart()->getLine(); auto while_id = std::to_string(_state.loop_stmt_count); - auto cond_block = build_BasicBlock("_loop_cond_" + while_id, _state.current_func, _state.current_bb->itr); - auto body_block = build_BasicBlock("_loop_body_" + while_id, _state.current_func, cond_block->itr); - auto next_block = build_BasicBlock("_loop_exit_" + while_id, _state.current_func, body_block->itr); - build_InstBranch(cond_block, _state.current_bb); + auto cond_block = BasicBlock::New("_loop_cond_" + while_id, _state.current_func, _state.current_bb->itr); + auto body_block = BasicBlock::New("_loop_body_" + while_id, _state.current_func, cond_block->itr); + auto next_block = BasicBlock::New("_loop_exit_" + while_id, _state.current_func, body_block->itr); + InstBranch::New(cond_block, _state.current_bb); _state.loop_stack.push_back({cond_block, body_block, next_block, _state.loop_stmt_count++}); // condition ctx->cond()->lOrExp()->true_block = body_block; @@ -1021,7 +1021,7 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) { // body _state.current_bb = body_block; visit(ctx->stmt()); - build_InstBranch(cond_block, _state.current_bb); + InstBranch::New(cond_block, _state.current_bb); // exit _state.loop_stack.pop_back(); _state.current_bb = next_block; @@ -1030,27 +1030,27 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) { std::any Visitor::visitBreakStmt(SysyParser::BreakStmtContext *ctx) { sysy_assert(!_state.loop_stack.empty()); - build_InstBranch(_state.loop_stack.back().next, _state.current_bb); - _state.current_bb = build_BasicBlock("_after_break", _state.current_func, _state.current_bb->itr); + InstBranch::New(_state.loop_stack.back().next, _state.current_bb); + _state.current_bb = BasicBlock::New("_after_break", _state.current_func, _state.current_bb->itr); return {}; } std::any Visitor::visitContinueStmt(SysyParser::ContinueStmtContext *ctx) { sysy_assert(!_state.loop_stack.empty()); - build_InstBranch(_state.loop_stack.back().cond, _state.current_bb); - _state.current_bb = build_BasicBlock("_after_continue", _state.current_func, _state.current_bb->itr); + InstBranch::New(_state.loop_stack.back().cond, _state.current_bb); + _state.current_bb = BasicBlock::New("_after_continue", _state.current_func, _state.current_bb->itr); return {}; } std::any Visitor::visitReturnStmt(SysyParser::ReturnStmtContext *ctx) { if (ctx->exp()) { auto exp = any_to_Value(visitExp(ctx->exp())); - build_InstReturn(exp, _state.current_bb); + InstReturn::New(exp, _state.current_bb); } else { - build_InstReturn(_state.current_bb); + InstReturn::New(_state.current_bb); } - auto new_bb = build_BasicBlock("after_ret", _state.current_func, _state.current_bb->itr); + auto new_bb = BasicBlock::New("after_ret", _state.current_func, _state.current_bb->itr); _state.current_bb = new_bb; return {}; } diff --git a/src/visitor_factory.cpp b/src/visitor_factory.cpp deleted file mode 100644 index f6e5a3a..0000000 --- a/src/visitor_factory.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "common.h" -#include "llir.h" -#include "visitor.h" -#include -#include - -namespace CompSysY { - -std::shared_ptr build_ConstantInt(const std::string &name, int value) { - auto lala = std::make_shared(name, value); - return lala; -} - -std::shared_ptr build_BasicBlock( - 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; -} - -std::shared_ptr build_InstLoad( - std::shared_ptr value, - TypePtr_t type, - std::shared_ptr parent_bb -) { - auto inst = std::make_shared(value, type, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstStore( - std::shared_ptr value, - std::shared_ptr pointer, - std::shared_ptr parent_bb -) { - auto inst = std::make_shared(value, pointer, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -// a little bit different, we put all alloca in the head of each basic block -std::shared_ptr build_InstAlloca( - const std::string &name, - TypePtr_t type, - std::shared_ptr parent_bb -) { - auto inst = std::make_shared(type, parent_bb); - inst->name = name; - auto func_head_bb = parent_bb->parent->bb_list.front(); - inst->inst_itr = func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst); - // parent_bb->inst_list.push_back(inst_alloca); - return inst; -} - -std::shared_ptr build_InstBinary( - InstTag inst_tag, - std::shared_ptr op1, - std::shared_ptr op2, - std::shared_ptr parent_bb -) { - std::shared_ptr inst; - if (InstTag::Lt <= inst_tag && inst_tag <= InstTag::Ne) { - inst = std::make_shared(inst_tag, TypeHelper::TYPE_I1, op1, op2, parent_bb); - } - else if (InstTag::Add <= inst_tag && inst_tag <= InstTag::Div) { - inst = std::make_shared(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb); - } - else { - panic("Invalid Binary Operation"); - } - assert(Type::isType(op1->type)); - assert(Type::isType(op2->type)); - if (!(Type::asType(op1->type)->int_type == Type::asType(op2->type)->int_type)) { - if (!(Value::is(op1) && Value::as(op1)->value == 0) - && !(Value::is(op2) && Value::as(op2)->value == 0)) { - LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string(); - assert(0); - } - } - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstZext(std::shared_ptr op, std::shared_ptr parent_bb) { - auto inst = std::make_shared(op, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstBranch( - ValuePtr_t cond, - BasicBlockPtr_t true_block, - BasicBlockPtr_t false_block, - BasicBlockPtr_t parent_bb -) { - auto inst = std::make_shared(cond, true_block, false_block, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) { - auto inst = std::make_shared(target_block, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstReturn(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb) { - auto inst = std::make_shared(ret_val, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstReturn(BasicBlockPtr_t parent_bb) { - auto inst = std::make_shared(parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstCall( - FunctionPtr_t func, - const std::vector &args, - BasicBlockPtr_t parent_bb -) { - auto inst = std::make_shared(func, args, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -std::shared_ptr build_InstGEP( - ValuePtr_t pointer, - const std::vector &indices, - BasicBlockPtr_t parent_bb -) { - auto inst = std::make_shared(pointer, indices, parent_bb); - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); - return inst; -} - -InstPhiPtr_t build_InstPhi( - TypePtr_t type, - const decltype(Function::bb_list) &incoming_vals, - BasicBlockPtr_t parent_bb, - const std::string &name -) { - auto inst = std::make_shared(type, incoming_vals, parent_bb); - inst->name = name; - inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); - return inst; -} - -} // namespace CompSysY \ No newline at end of file diff --git a/src/visitor_llir_gen.cpp b/src/visitor_llir_gen.cpp index d0f7030..a5c80db 100644 --- a/src/visitor_llir_gen.cpp +++ b/src/visitor_llir_gen.cpp @@ -104,11 +104,9 @@ static void _build_arr_init_list( static void _gen_blocks(std::ostream &ostr, const std::list &block_list, int reg_count) { // first pass, allocate sequence number for (auto block_itr = block_list.begin(); block_itr != block_list.end(); ++block_itr) { - auto block = *block_itr; - sysy_assert(block->ir_seqno == -1); // multi-alloc is error + auto block = *block_itr; block->ir_seqno = reg_count++; for (auto inst : block->inst_list) { - sysy_assert(inst->ir_seqno == -1); // multi-alloc is error switch (inst->tag) { // These are not to get a seqno case InstTag::Br: @@ -160,22 +158,22 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl VLOG(7) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string(); switch (_inst->tag) { case InstTag::Br: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno == -1); ostr << "br "; if (inst->operand_list.size() == 1) { - assert(Value::is(inst->operand_list[0])); - auto bb_dest = Value::as(inst->operand_list[0]); + assert(shared_cast(inst->operand_list[0])); + auto bb_dest = shared_cast(inst->operand_list[0]); VLOG(7) << "br to " << bb_dest->name; assert(bb_dest->ir_seqno >= 0); ostr << "label %" << bb_dest->ir_seqno; } else { - assert(Value::is(inst->operand_list[0])); + assert(shared_cast(inst->operand_list[0])); assert(Type::isType(inst->operand_list[0]->type)); - auto cond = Value::as(inst->operand_list[0]); - auto bb_true = Value::as(inst->operand_list[1]); - auto bb_false = Value::as(inst->operand_list[2]); + auto cond = shared_cast(inst->operand_list[0]); + auto bb_true = shared_cast(inst->operand_list[1]); + auto bb_false = shared_cast(inst->operand_list[2]); if (!Type::asType(cond->type)->isI1()) { LOG(ERROR) << "Expect cond evals to i1: " << cond->to_string(); panic("Grammar check"); @@ -188,7 +186,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::Ret: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno == -1); ostr << "ret "; if (inst->operand_list.size() == 0) { @@ -196,17 +194,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl ostr << "void"; } else { - if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); assert(op0->ir_seqno >= 0); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } else { @@ -217,38 +215,38 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::Store: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno == -1); ostr << "store "; - if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); assert(op0->ir_seqno >= 0); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << ", "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << ", "; } else { LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string(); assert(0); } - if (Value::is(inst->operand_list[1])) { - auto op1 = Value::as(inst->operand_list[1]); + if (shared_cast(inst->operand_list[1])) { + auto op1 = shared_cast(inst->operand_list[1]); ostr << op1->type->to_IR_string() << " @" << op1->name; } - else if (Value::is(inst->operand_list[1])) { - auto op1 = Value::as(inst->operand_list[1]); + else if (shared_cast(inst->operand_list[1])) { + auto op1 = shared_cast(inst->operand_list[1]); assert(op1->ir_seqno >= 0); ostr << op1->type->to_IR_string() << " %" << op1->ir_seqno; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } else { @@ -260,9 +258,9 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl } // Call's seqno is dependent on its return type case InstTag::Call: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); LOG(DEBUG) << inst->operand_list[0]->to_string(); - auto func = Value::as(inst->operand_list[0]); + auto func = shared_cast(inst->operand_list[0]); auto func_type = Type::asType(func->type); if (Type::isType(func_type->return_type)) { assert(inst->ir_seqno == -1); @@ -275,17 +273,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl ostr << func->name << "("; if (inst->operand_list.size() > 1) { for (int i = 1; i < inst->operand_list.size(); ++i) { - if (Value::is(inst->operand_list[i])) { - auto op0 = Value::as(inst->operand_list[i]); + if (shared_cast(inst->operand_list[i])) { + auto op0 = shared_cast(inst->operand_list[i]); assert(op0->ir_seqno >= 0); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno; } - else if (Value::is(inst->operand_list[i])) { - auto op0 = Value::as(inst->operand_list[i]); + else if (shared_cast(inst->operand_list[i])) { + auto op0 = shared_cast(inst->operand_list[i]); ostr << op0->to_IR_string(); } - else if (Value::is(inst->operand_list[i])) { - auto op0 = Value::as(inst->operand_list[i]); + else if (shared_cast(inst->operand_list[i])) { + auto op0 = shared_cast(inst->operand_list[i]); ostr << op0->to_IR_string(); } else { @@ -312,36 +310,36 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl case InstTag::Ne: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); ostr << "%" << inst->ir_seqno << " = " << inst->tag_string() << " "; - if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); assert(op0->ir_seqno >= 0); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << ", "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << ", "; } else { LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string(); assert(0); } - if (Value::is(inst->operand_list[1])) { - auto op1 = Value::as(inst->operand_list[1]); + if (shared_cast(inst->operand_list[1])) { + auto op1 = shared_cast(inst->operand_list[1]); assert(op1->ir_seqno >= 0); ostr << "%" << op1->ir_seqno; } - else if (Value::is(inst->operand_list[1])) { - auto op1 = Value::as(inst->operand_list[1]); + else if (shared_cast(inst->operand_list[1])) { + auto op1 = shared_cast(inst->operand_list[1]); ostr << op1->value; } - else if (Value::is(inst->operand_list[1])) { - auto op1 = Value::as(inst->operand_list[1]); + else if (shared_cast(inst->operand_list[1])) { + auto op1 = shared_cast(inst->operand_list[1]); ostr << "%" << op1->ir_seqno; } else { @@ -351,21 +349,20 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::Load: { - auto inst = Value::as(_inst); - assert(inst->ir_seqno != -1); + auto inst = shared_cast(_inst); assert(Type::isType(inst->operand_list[0]->type)); ostr << "%" << inst->ir_seqno << " = load " << inst->type->to_IR_string() << ", "; - if (Value::is(inst->operand_list[0])) { - auto op = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op = shared_cast(inst->operand_list[0]); ostr << op->type->to_IR_string() << " @" << op->name; } - else if (Value::is(inst->operand_list[0])) { - auto op = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op = shared_cast(inst->operand_list[0]); assert(op->ir_seqno >= 0); ostr << op->type->to_IR_string() << " %" << op->ir_seqno; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } else { @@ -375,21 +372,21 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::GEP: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno >= 0); auto pointer_type = Type::asType(inst->operand_list[0]->type); ostr << "%" << inst->ir_seqno << " = getelementptr " << pointer_type->pointed_type->to_IR_string() << ", "; - if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string(); } else { @@ -402,28 +399,27 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::Alloca: { - auto inst = Value::as(_inst); - assert(inst->ir_seqno != -1); + auto inst = shared_cast(_inst); auto pointer_type = Type::asType(inst->type); ostr << "%" << inst->ir_seqno << " = alloca " << pointer_type->pointed_type->to_IR_string() << ", align 4"; ostr << " ;" << inst->name; break; } case InstTag::Zext: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno >= 0); ostr << "%" << inst->ir_seqno << " = zext "; - if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); assert(op0->ir_seqno >= 0); ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << " to "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << "to "; } - else if (Value::is(inst->operand_list[0])) { - auto op0 = Value::as(inst->operand_list[0]); + else if (shared_cast(inst->operand_list[0])) { + auto op0 = shared_cast(inst->operand_list[0]); ostr << op0->to_IR_string() << "to "; } else { @@ -434,26 +430,26 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl break; } case InstTag::Phi: { - auto inst = Value::as(_inst); + auto inst = shared_cast(_inst); assert(inst->ir_seqno >= 0); ostr << "%" << inst->ir_seqno << " = phi " << inst->type->to_IR_string() << " "; for (int i = 0; i < inst->operand_list.size(); ++i) { auto op = inst->operand_list[i]; ostr << "["; - if (Value::is(op)) { - auto op0 = Value::as(op); + if (shared_cast(op)) { + auto op0 = shared_cast(op); ostr << "@" << op0->name; } - else if (Value::is(op)) { - auto op0 = Value::as(op); + else if (shared_cast(op)) { + auto op0 = shared_cast(op); ostr << "%" << op0->ir_seqno; } - else if (Value::is(op)) { - auto op0 = Value::as(op); + else if (shared_cast(op)) { + auto op0 = shared_cast(op); ostr << "%" << op0->ir_seqno; } - else if (Value::is(op)) { - auto op0 = Value::as(op); + else if (shared_cast(op)) { + auto op0 = shared_cast(op); ostr << op0->value; } else {