diff --git a/docs/ARMv7-cheat-sheet.pdf b/docs/ARMv7-cheat-sheet.pdf new file mode 100644 index 0000000..56da90e Binary files /dev/null and b/docs/ARMv7-cheat-sheet.pdf differ diff --git a/include/common.h b/include/common.h index 307f42b..86293f6 100644 --- a/include/common.h +++ b/include/common.h @@ -1,6 +1,7 @@ #pragma once #include "3rdparty/easylogging++.h" #include +#include #include #include #include @@ -20,6 +21,13 @@ inline sptr(DST) shared_cast(SRC src) { return std::dynamic_pointer_cast(src); } +template +inline sptr(DST) strict_shared_cast(SRC src) { + sptr(DST) dst = std::dynamic_pointer_cast(src); + assert(dst); + return dst; +} + #define FIND(container, val) std::find(container.begin(), container.end(), val) #define panic(message) \ diff --git a/include/llir.h b/include/llir.h index 4ab1e7f..e1c6f23 100644 --- a/include/llir.h +++ b/include/llir.h @@ -2,4 +2,11 @@ #include "llir_instruction.h" #include "llir_module.h" #include "llir_type.h" -#include "llir_value.h" \ No newline at end of file +#include "llir_value.h" + +namespace CompSysY { +// Utilities +TypePtr_t get_pointed_type(TypePtr_t ptr); +unsigned get_type_size(TypePtr_t ir_type); +unsigned get_pointed_type_size(TypePtr_t ir_type); +} // namespace CompSysY \ No newline at end of file diff --git a/include/llir_instruction.h b/include/llir_instruction.h index 8cc09a4..8365d29 100644 --- a/include/llir_instruction.h +++ b/include/llir_instruction.h @@ -31,8 +31,7 @@ enum class InstTag { Gt, Eq, Ne, - And, - Or, + // And, Or, Br, Call, Ret, @@ -53,7 +52,7 @@ public: int ir_seqno = -1; InstTag tag; BasicBlockPtr_t parent_bb; - // decltype(parent_bb->inst_list.begin()) inst_itr_in_parent; + decltype(BasicBlock::inst_list.begin()) 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() { @@ -69,8 +68,8 @@ public: case InstTag::Gt: return "icmp sgt"; case InstTag::Eq: return "icmp eq"; case InstTag::Ne: return "icmp ne"; - case InstTag::And: return "and"; - case InstTag::Or: return "or"; + // case InstTag::And: return "and"; + // case InstTag::Or: return "or"; case InstTag::Br: return "br"; case InstTag::Call: return "call"; case InstTag::Ret: return "ret"; @@ -244,7 +243,7 @@ public: } else if (Type::isType(pointed_type)) { for (int i = 1; i < indices.size(); ++i) { - pointed_type = shared_cast(pointed_type)->element_type; + pointed_type = shared_cast(pointed_type)->elem_type; } return pointed_type; } diff --git a/include/llir_type.h b/include/llir_type.h index ddedf57..a6bc64b 100644 --- a/include/llir_type.h +++ b/include/llir_type.h @@ -111,11 +111,12 @@ public: class ArrayType : public Type { public: - TypePtr_t element_type = TypeHelper::TYPE_I32; - int element_count = 0; + TypePtr_t elem_type = TypeHelper::TYPE_I32; + int elem_count = 0; // current dim size + int type_size = 0; // = dim_size * size(elem_type) ArrayType() : Type(TypeTag::ArrayType) {} ArrayType(TypePtr_t element_type, int element_count) - : Type(TypeTag::ArrayType), element_count(element_count), element_type(element_type) {} + : Type(TypeTag::ArrayType), elem_count(element_count), elem_type(element_type) {} static std::shared_ptr build_from_list(const std::vector &dim_list) { TypePtr_t array_type = TypeHelper::TYPE_I32; sysy_assert(dim_list.size() != 0); @@ -125,17 +126,16 @@ public: return std::dynamic_pointer_cast(array_type); } virtual std::string to_string() override { - return "Array[" + std::to_string(element_count) + " x " + element_type->to_string() + "]"; + return "Array[" + std::to_string(elem_count) + " x " + elem_type->to_string() + "]"; } virtual std::string to_IR_string() override { - return "[" + std::to_string(element_count) + " x " + element_type->to_IR_string() + "]"; + return "[" + std::to_string(elem_count) + " x " + elem_type->to_IR_string() + "]"; } }; class PointerType : public Type { public: TypePtr_t pointed_type = TypeHelper::TYPE_I32; - PointerType() : Type(TypeTag::PointerType) {} PointerType(TypePtr_t pointed_type) : Type(TypeTag::PointerType), pointed_type(pointed_type) {} static auto make_shared(TypePtr_t pointed_type) { return std::make_shared(pointed_type); @@ -146,12 +146,6 @@ public: virtual std::string to_IR_string() override { return pointed_type->to_IR_string() + "*"; } - - static TypePtr_t pointedType(TypePtr_t ptr) { - assert(Type::isType(ptr)); - auto pointer_type = Type::asType(ptr); - return pointer_type->pointed_type; - } }; class FunctionType : public Type { @@ -166,6 +160,4 @@ public: } }; -TypePtr_t pointed_type(TypePtr_t ptr); - } // namespace CompSysY \ No newline at end of file diff --git a/include/llir_value.h b/include/llir_value.h index 3e19d22..2c63b7f 100644 --- a/include/llir_value.h +++ b/include/llir_value.h @@ -204,7 +204,7 @@ public: : Constant(name, type), value_list(value_list) {} int real_size() const { - return std::dynamic_pointer_cast(type)->element_count; + return std::dynamic_pointer_cast(type)->elem_count; } static std::shared_ptr make_shared( const std::string &name, diff --git a/include/mc_inst.h b/include/mc_inst.h index e0c8bab..7150e50 100644 --- a/include/mc_inst.h +++ b/include/mc_inst.h @@ -4,7 +4,7 @@ using std::make_shared; -namespace codegen { +namespace CompSysY { // a?, t?, ra are caller-saved // s? are callee-saved @@ -46,7 +46,11 @@ enum class RV64Reg { // riscv calling convention see: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc -const int XLEN = 8; +const unsigned XLEN = 8; +const unsigned XLEN_MASK = XLEN - 1; +inline unsigned xlen_rnd_up(unsigned src) { + return (src & XLEN_MASK) ? (src & (~XLEN_MASK)) + XLEN : src; +} inline std::string RV64_RegName(RV64Reg reg) { std::string regname = "x" + std::to_string((int)reg); @@ -68,14 +72,11 @@ public: enum class OpTag { Virt, Imm, - Reg, + PreColor, } op_type = OpTag::Virt; int value = ~0; -private: MOperand(OpTag tag, int val) : op_type(tag), value(val) {} - -public: static sptr(MOperand) NewVirtReg(int reg_no) { auto mop = std::make_shared(OpTag::Virt, reg_no); return mop; @@ -87,46 +88,62 @@ public: } static sptr(MOperand) NewReg(RV64Reg phy_reg) { - auto mop = std::make_shared(OpTag::Reg, (int)phy_reg); + auto mop = std::make_shared(OpTag::PreColor, (int)phy_reg); return mop; } }; +enum class MInstTag { + Add, + Sub, + Mul, + Div, + Mod, + Lt, + Le, + Ge, + Gt, + Eq, + Ne, + And, + Or, + Lsh, // sll + Rsh, // srl,sra + Move, // actually a pseudo, mv = addi rt, rs, 0 + Branch, + Jmp, + Ret, + Load, + Store, + Compare, + Call, + Globsym, + Comment, +}; + +inline MInstTag inverse_cond(MInstTag src_tag) { + switch (src_tag) { + case MInstTag::Lt: return MInstTag::Ge; + case MInstTag::Le: return MInstTag::Gt; + case MInstTag::Ge: return MInstTag::Lt; + case MInstTag::Gt: return MInstTag::Le; + case MInstTag::Eq: return MInstTag::Ne; + case MInstTag::Ne: return MInstTag::Eq; + default: assert(0); + } +} + class MInst { public: - enum class MInstTag { - Add, - Sub, - Rsb, - Mul, - Div, - Mod, - Lt, - Le, - Ge, - Gt, - Eq, - Ne, - And, - Or, - Move, // actually a pseudo, mv = addi rt, rs, 0 - Branch, - Jump, - Return, - Load, - Store, - Compare, - Call, - Global, - } tag; + MInstTag inst_tag; sptr(MBasicBlock) parent_bb; - MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : tag(tag), parent_bb(parent_bb) {} + MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : inst_tag(tag), parent_bb(parent_bb) {} }; class MBasicBlock { public: - sptr(antlrSysY::BasicBlock) ir_bb; + sptr(BasicBlock) ir_bb; sptr(MFunction) parent_func; std::list inst_list; std::list pred_list; @@ -139,32 +156,39 @@ public: class MFunction { public: std::list bb_list; - sptr(antlrSysY::Function) ir_func; + sptr(Function) ir_func; std::list stack_arg_reloc; + unsigned stack_size; unsigned virt_reg_cnt = 0; }; -class MGlobalVar { -public: -}; - class MCModule { public: std::list function_list; - std::list global_list; - void IR2MC(const antlrSysY::Module &ir_module); + std::list global_list; + void IR2MC(const Module &ir_module); }; class MInstBinary : public MInst { public: + sptr(MOperand) dst; + sptr(MOperand) op1; + sptr(MOperand) op2; + MInstBinary(MInstTag type, sptr(MBasicBlock) parent_bb) : MInst(type, parent_bb) {} + + static sptr(MInstBinary) New(MInstTag type, sptr(MBasicBlock) parent_bb) { + auto inst = make_shared(type, parent_bb); + parent_bb->inst_list.push_back(inst); + return inst; + } }; class MInstJump : public MInst { public: sptr(MBasicBlock) target; - MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jump, parent_bb) {} + MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jmp, parent_bb) {} static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) { auto inst = make_shared(parent_bb); @@ -173,6 +197,20 @@ public: } }; +class MInstBranch : public MInst { +public: + sptr(MBasicBlock) target; + sptr(MOperand) op1; + sptr(MOperand) op2; + MInstTag branch_tag; + MInstBranch(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Branch, parent_bb) {} + static sptr(MInstBranch) New(sptr(MBasicBlock) parent_bb) { + auto inst = make_shared(parent_bb); + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + class MInstLoad : public MInst { public: sptr(MOperand) dst; @@ -187,6 +225,20 @@ public: } }; +class MInstStore : public MInst { +public: + sptr(MOperand) data; + sptr(MOperand) addr; + sptr(MOperand) offset; + MInstStore(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Load, parent_bb) {} + + static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb) { + auto inst = make_shared(parent_bb); + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + class MInstMove : public MInst { public: sptr(MOperand) dst; @@ -201,15 +253,64 @@ public: return inst; } static sptr(MInstMove) New(sptr(MInst) rel_inst, bool insert_after = false) { - auto parent_bb = rel_inst->parent_bb; - auto inst = make_shared(parent_bb); + auto parent_bb = rel_inst->parent_bb; + auto inst = make_shared(parent_bb); auto rel_inst_itr = FIND(parent_bb->inst_list, rel_inst); assert(rel_inst_itr != parent_bb->inst_list.end()); - if (insert_after) - std::advance(rel_inst_itr, 1); + if (insert_after) std::advance(rel_inst_itr, 1); parent_bb->inst_list.insert(rel_inst_itr, inst); return inst; } }; -} // namespace codegen \ No newline at end of file +class MInstSymbol : public MInst { +public: + sptr(MOperand) dst; + sptr(GlobalVar) symbol; + MInstSymbol(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Globsym, parent_bb) {} + static sptr(MInstSymbol) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) { + auto inst = make_shared(parent_bb); + if (insert_begin) + parent_bb->inst_list.push_front(inst); + else + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + +class MInstReturn : public MInst { +public: + MInstReturn(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Ret, parent_bb) {} + static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) { + auto inst = make_shared(parent_bb); + if (insert_begin) + parent_bb->inst_list.push_front(inst); + else + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + +class MInstComment : public MInst { +public: + std::string comment; + MInstComment(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Comment, parent_bb) {} + static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb) { + auto inst = make_shared(parent_bb); + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + +class MInstCall : public MInst { +public: + sptr(Function) ir_func; + MInstCall(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Call, parent_bb) {} + static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb) { + auto inst = make_shared(parent_bb); + parent_bb->inst_list.push_back(inst); + return inst; + } +}; + +} // namespace CompSysY \ No newline at end of file diff --git a/src/llir.cpp b/src/llir.cpp new file mode 100644 index 0000000..fd1db83 --- /dev/null +++ b/src/llir.cpp @@ -0,0 +1,37 @@ +#include "llir.h" + +/* +Utilities for LLIR +*/ + +namespace CompSysY { + +TypePtr_t get_pointed_type(TypePtr_t ptr) { + assert(Type::isType(ptr)); + auto pointer_type = Type::asType(ptr); + return pointer_type->pointed_type; +} + +unsigned get_type_size(TypePtr_t ir_type) { + if (auto arr_ty = shared_cast(ir_type)) { + if (!arr_ty->type_size) arr_ty->type_size = arr_ty->elem_count * get_type_size(arr_ty->elem_type); + return arr_ty->type_size; + } + else if (auto int_ty = shared_cast(ir_type)) { + assert(int_ty->isI32()); + return 4; + } + assert(0 && "Only IntegerType|ArrayType have size"); +} + +unsigned get_pointed_type_size(TypePtr_t ir_type) { + if (auto arr_ty = shared_cast(ir_type)) { + return get_type_size(arr_ty->elem_type); + } + else if (auto ptr_ty = shared_cast(ir_type)) { + return get_type_size(ptr_ty->pointed_type); + } + assert(0 && "Only PointerType|ArrayType has pointed type"); +} + +} // namespace CompSysY \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 53a1d5a..817e065 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,7 +127,7 @@ int main(int argc, const char **argv) { // std::cout << tree->toStringTree(&parser) << std::endl << std::endl; MCModule mc_module; - // mc_module.IR2MC(visitor.module); + mc_module.IR2MC(visitor.module); return 0; } \ No newline at end of file diff --git a/src/mc_codegen.cpp b/src/mc_codegen.cpp index fe78fd5..a86f0ef 100644 --- a/src/mc_codegen.cpp +++ b/src/mc_codegen.cpp @@ -5,47 +5,77 @@ using std::make_shared; -namespace codegen { +namespace CompSysY { + +static auto gen_imm(int imm, sptr(MBasicBlock) mc_bb) { + auto operand = MOperand::NewImm(imm); + // 12 bit signed imm for I/S-type + if (-2048 <= imm && imm <= 2047) { + return operand; + } + // load to register, should use pseudo `mv` + // TODO TrivialCompiler added a opt trick here, insert before a control tansfer? + auto vr = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); + auto inst_move = MInstMove::New(mc_bb); + inst_move->src = operand; + inst_move->dst = vr; + return vr; +} static sptr(MOperand) value2moperand( - sptr(antlrSysY::Value) ir_value, + sptr(Value) ir_value, sptr(MBasicBlock) mc_bb, - std::unordered_map &val2mop + std::unordered_map &val2mop ) { - if (auto fparam = shared_cast(ir_value)) { + if (auto fparam = shared_cast(ir_value)) { auto itr = val2mop.find(ir_value); if (itr != val2mop.end()) { return itr->second; } - else { - auto vr = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); - val2mop.insert({ir_value, vr}); - auto ir_func = mc_bb->parent_func->ir_func; - auto fparam_itr = FIND(ir_func->fparam_list, fparam); - assert(fparam_itr != ir_func->fparam_list.end()); - auto fparam_ndx = std::distance(ir_func->fparam_list.begin(), fparam_itr); - // according to RV call conv, we can have a0-a7 for params - if (fparam_ndx < 8) { - // copy param as an vr in func entry - auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), true); - inst_move->src = MOperand::NewReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx)); - inst_move->dst = vr; - } - else { - // read from stack, sp + (i - 8) * 8, since ABI requires the stack to be aligned by XLEN=64 - // this need to be further re-located since sp may have changed - // FramePtr won't get used here, for perf reason. Ref: - // https://stackoverflow.com/questions/13006371/does-omitting-the-frame-pointers-really-have-a-positive-effect-on-performance-an - // auto vr_tmp = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); - auto inst_load = MInstLoad::New(mc_bb); // ld vr, (i-8)*8(sp) - // auto inst_move = MInstMove::New(inst_load); // lui vr_t, - inst_load->addr = MOperand::NewReg(RV64Reg::sp); - inst_load->offset = MOperand::NewImm((fparam_ndx - 8) * XLEN); - inst_load->dst = vr; - mc_bb->parent_func->stack_arg_reloc.push_back(inst_load); - } - return vr; + auto vr = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); + val2mop.insert({ir_value, vr}); + auto ir_func = mc_bb->parent_func->ir_func; + auto fparam_itr = FIND(ir_func->fparam_list, fparam); + assert(fparam_itr != ir_func->fparam_list.end()); + auto fparam_ndx = std::distance(ir_func->fparam_list.begin(), fparam_itr); + // according to RV call conv, we can have a0-a7 for params + if (fparam_ndx < 8) { + // copy param as an vr in func entry + auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), true); + inst_move->src = MOperand::NewReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx)); + inst_move->dst = vr; } + else { + // read from stack, sp + (i - 8) * 8, since ABI requires the stack to be aligned by XLEN=64 + // this need to be further re-located since sp may have changed + // FramePtr won't get used here, for perf reason. Ref: + // https://stackoverflow.com/questions/13006371/does-omitting-the-frame-pointers-really-have-a-positive-effect-on-performance-an + // TODO Trivial Compiler(THU2020) use an addition move, but I am not sure why, deleted temporally + // auto vr_tmp = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); + auto inst_load = MInstLoad::New(mc_bb); // ld vr, (i-8)*8(sp) + // auto inst_move = MInstMove::New(inst_load); // lui vr_t, + inst_load->addr = MOperand::NewReg(RV64Reg::sp); + inst_load->offset = MOperand::NewImm((fparam_ndx - 8) * XLEN); + inst_load->dst = vr; + mc_bb->parent_func->stack_arg_reloc.push_back(inst_load); + } + 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::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); + val2mop.insert({ir_value, vr}); + inst_symld->symbol = glob; + inst_symld->dst = vr; + return vr; + } + else if (auto constant = shared_cast(ir_value)) { + auto imm = constant->value; + return gen_imm(imm, mc_bb); } else { // plain situation @@ -61,9 +91,10 @@ static sptr(MOperand) value2moperand( } } -void MCModule::IR2MC(const antlrSysY::Module &ir_module) { +void MCModule::IR2MC(const Module &ir_module) { + // Simply copy globals, since they don't need any translation for (auto glob : ir_module.global_var_list) { - // TODO copy globals from ir + this->global_list.push_back(glob); } for (auto func : ir_module.function_list) { @@ -73,11 +104,12 @@ void MCModule::IR2MC(const antlrSysY::Module &ir_module) { mc_func->ir_func = func; // copy pred/succ info - std::unordered_map bb_ir2mc; + std::unordered_map bb_ir2mc; for (auto bb : func->bb_list) { auto mc_bb = make_shared(); mc_func->bb_list.push_back(mc_bb); mc_bb->ir_bb = bb; + mc_bb->parent_func = mc_func; bb_ir2mc.insert({bb, mc_bb}); } for (auto bb : func->bb_list) { @@ -92,17 +124,378 @@ void MCModule::IR2MC(const antlrSysY::Module &ir_module) { mc_bb->pred_list.push_back(mc_pred); } } - + std::unordered_map mp_val2op; + std::unordered_map mp_br2icmp; // instruction translate for (auto bb : func->bb_list) { auto mc_bb = bb_ir2mc[bb]; for (auto inst : bb->inst_list) { - if (auto li = shared_cast(inst)) { - auto mc_li = MInstLoad::New(mc_bb); + if (auto ld = shared_cast(inst)) { + auto addr = value2moperand(ld->operand_list[0], mc_bb, mp_val2op); + auto mc_li = MInstLoad::New(mc_bb); + mc_li->addr = addr; + mc_li->dst = value2moperand(ld, mc_bb, mp_val2op); + mc_li->offset = nullptr; + continue; } + if (auto st = shared_cast(inst)) { + auto data = value2moperand(st->operand_list[0], mc_bb, mp_val2op); + auto addr = value2moperand(st->operand_list[1], mc_bb, mp_val2op); + auto mc_li = MInstStore::New(mc_bb); + mc_li->addr = addr; + mc_li->data = data; + mc_li->offset = nullptr; + continue; + } + if (auto gep = shared_cast(inst)) { + // gep ptr, index0, index1 + // tgt_addr = ptr + index0 * sizeof(elem_ty) + index1 * sizeof(elem_ty->elem_ty) + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto ptr = value2moperand(inst->operand_list[0], mc_bb, mp_val2op); + auto index0 = value2moperand(inst->operand_list[1], mc_bb, mp_val2op); + decltype(index0) index1 = nullptr; + assert(inst->operand_list.size() <= 3); + if (inst->operand_list.size() == 3) { + assert(index0->op_type == MOperand::OpTag::Imm && index0->value == 0); + index1 = value2moperand(inst->operand_list[2], mc_bb, mp_val2op); + } + // %dst = getelementptr [2x[3xi32]] [2x[3xi32]]* %ptr, i32 0, i32 1 + auto ptr_type = gep->operand_list[0]->type; + auto elem_type = shared_cast(ptr_type)->pointed_type; + + if (!index0->value || !index1 || !index1->value) { + // a shortcut for zero gep + auto inst_mv = MInstMove::New(mc_bb); + inst_mv->dst = dst; + inst_mv->src = ptr; + VLOG(6) << "trivial gep"; + } + else if (!index1) { + // index on same dim: addr = ptr + index0 * sizeof(elem_ty) + auto elem_size = get_type_size(elem_type); + auto elem_size_imm = gen_imm(elem_size, mc_bb); + auto vr = MOperand::NewVirtReg(mc_func->virt_reg_cnt++); + auto inst_mul = MInstBinary::New(MInstTag::Mul, mc_bb); + inst_mul->dst = vr; + inst_mul->op1 = index0; + inst_mul->op2 = elem_size_imm; + auto inst_add = MInstBinary::New(MInstTag::Add, mc_bb); + inst_add->dst = dst; + inst_add->op1 = ptr; + inst_add->op2 = vr; + VLOG(6) << "gep ptr + elem_ty * index"; + } + else { + // index on sub dim: addr = ptr + index1 * sizeof(elem_ty.elem_ty) + auto elem_elem_size = get_pointed_type_size(elem_type); + auto elem_elem_size_imm = gen_imm(elem_elem_size, mc_bb); + auto vr = MOperand::NewVirtReg(mc_func->virt_reg_cnt++); + auto inst_mul = MInstBinary::New(MInstTag::Mul, mc_bb); + inst_mul->dst = vr; + inst_mul->op1 = index0; + inst_mul->op2 = elem_elem_size_imm; + auto inst_add = MInstBinary::New(MInstTag::Add, mc_bb); + inst_add->dst = dst; + inst_add->op1 = ptr; + inst_add->op2 = vr; + VLOG(6) << "gep ptr + elem_ty.elem_ty * index"; + } + } + else if (auto alc = shared_cast(inst)) { + unsigned alloca_size = 0; + auto allocated_type = get_pointed_type(alc->type); + if (shared_cast(allocated_type) || shared_cast(allocated_type)) { + // int on stack has to be aligned + // whereas, ptr is possible when a array from fparam: `%arr = alloca [10xi32]*` + alloca_size = XLEN; + } + else { + assert(shared_cast(allocated_type)); + alloca_size = get_type_size(allocated_type); + // align array on stack to XLEN + alloca_size = xlen_rnd_up(alloca_size); + } + assert(alloca_size && !(alloca_size & XLEN_MASK)); + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto stk_sz_imm = gen_imm(mc_func->stack_size, mc_bb); + auto inst_add = MInstBinary::New(MInstTag::Add, mc_bb); + inst_add->dst = dst; + inst_add->op1 = MOperand::NewReg(RV64Reg::sp); + inst_add->op2 = stk_sz_imm; + // dont forget to record stack usage + mc_func->stack_size += alloca_size; + } + else if (auto ret = shared_cast(inst)) { + if (ret->operand_list.size()) { + auto retval = value2moperand(ret->operand_list[0], mc_bb, mp_val2op); + auto inst_mv = MInstMove::New(mc_bb); + inst_mv->src = retval; + inst_mv->dst = MOperand::NewReg(RV64Reg::a0); + } + MInstReturn::New(mc_bb); + } + else if (auto cal = shared_cast(inst)) { + auto target_func = cal->operand_list[0]; + int nparams = cal->operand_list.size() - 1; + for (int i = 1; i < cal->operand_list.size(); ++i) { + auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op); + if (i <= 8) { + auto inst_move = MInstMove::New(mc_bb); + inst_move->src = rparam; + inst_move->dst = MOperand::NewReg(RV64_RegOffset(RV64Reg::a0, i - 1)); + } + else { + int st_off = -(nparams - (i - 1)) * XLEN; + auto st_off_imm = gen_imm(st_off, mc_bb); + auto inst_store = MInstStore::New(mc_bb); + inst_store->addr = MOperand::NewReg(RV64Reg::sp); + inst_store->offset = st_off_imm; + inst_store->data = rparam; + } + } + if (nparams > 8) { + // sp -= (n-8)*8 + auto add_inst = new MInstBinary(MInstTag::Sub, mc_bb); + add_inst->dst = MOperand::NewReg(RV64Reg::sp); + add_inst->op1 = MOperand::NewReg(RV64Reg::sp); + add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); + } + + auto inst_call = MInstCall::New(mc_bb); + inst_call->ir_func = strict_shared_cast(cal->operand_list[0]); + + if (nparams > 8) { + // sp += (n-8)*8 + auto add_inst = new MInstBinary(MInstTag::Add, mc_bb); + add_inst->dst = MOperand::NewReg(RV64Reg::sp); + add_inst->op1 = MOperand::NewReg(RV64Reg::sp); + add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); + } + // handle return value, if exist + if (shared_cast(cal->type)) { + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto inst_mv = MInstMove::New(mc_bb); + inst_mv->src = MOperand::NewReg(RV64Reg::a0); + inst_mv->dst = dst; + } + } + else if (auto br = shared_cast(inst)) { + if (br->operand_list.size() == 1) { + auto inst_jump = MInstJump::New(mc_bb); + auto target = br->operand_list.front(); + inst_jump->target = bb_ir2mc.at(strict_shared_cast(target)); + } + else { + if (mp_br2icmp.find(dynamic_cast(br.get())) != mp_br2icmp.end()) { + auto cond = mp_br2icmp.at(dynamic_cast(br.get())); + auto op1 = value2moperand(cond->operand_list[0], mc_bb, mp_val2op); + auto op2 = value2moperand(cond->operand_list[1], mc_bb, mp_val2op); + auto inst_br = MInstBranch::New(mc_bb); + inst_br->op1 = op1; + inst_br->op2 = op2; + switch (cond->tag) { + case InstTag::Lt: inst_br->branch_tag = MInstTag::Lt; break; + case InstTag::Le: inst_br->branch_tag = MInstTag::Le; break; + case InstTag::Ge: inst_br->branch_tag = MInstTag::Ge; break; + case InstTag::Gt: inst_br->branch_tag = MInstTag::Gt; break; + case InstTag::Eq: inst_br->branch_tag = MInstTag::Eq; break; + case InstTag::Ne: inst_br->branch_tag = MInstTag::Ne; break; + default: assert(0); + } + if (*std::next(mc_bb->ir_bb->itr) == br->operand_list[1]) { + // true branch is the next block, while false branch is faraway + // branch to false branch and inverse the condition + inst_br->branch_tag = inverse_cond(inst_br->branch_tag); + inst_br->target = bb_ir2mc.at(strict_shared_cast(br->operand_list[1])); + } + else if (*std::next(mc_bb->ir_bb->itr) == br->operand_list[2]) { + inst_br->target = bb_ir2mc.at(strict_shared_cast(br->operand_list[2])); + } + else { + panic("Unexpected branch pattern"); + } + } + else { + auto cond = value2moperand(br->operand_list[0], mc_bb, mp_val2op); + auto inst_br = MInstBranch::New(mc_bb); + inst_br->op1 = cond; + inst_br->op2 = MOperand::NewReg(RV64Reg::x0); + inst_br->branch_tag = MInstTag::Ne; + if (*std::next(mc_bb->ir_bb->itr) == br->operand_list[1]) { + inst_br->branch_tag = inverse_cond(inst_br->branch_tag); + inst_br->target = bb_ir2mc.at(strict_shared_cast(br->operand_list[1])); + } + else if (*std::next(mc_bb->ir_bb->itr) == br->operand_list[2]) { + inst_br->target = bb_ir2mc.at(strict_shared_cast(br->operand_list[2])); + } + else { + panic("Unexpected branch pattern"); + } + } + } + } + else if (auto bin = shared_cast(inst)) { + auto op1 = inst->operand_list[0]; + auto op2 = inst->operand_list[1]; + // Frontend should promise constant expr to be eliminated + // assert(!(shared_cast(op1) && shared_cast(op2))); + if (shared_cast(op1) && shared_cast(op2)) { + LOG(WARNING) << "Constant expr not eliminated: " << bin->to_string(); + auto res = shared_cast(op1)->value + shared_cast(op2)->value; + auto src_imm = gen_imm(res, mc_bb); + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto inst_mv = MInstMove::New(mc_bb); + inst_mv->dst = dst; + inst_mv->src = src_imm; + continue; + } + // 2^n replacement + auto _is_const_mul_power2 = [&]() -> sptr(ConstantInt) { + if (!(bin->tag == InstTag::Mul)) return nullptr; + if (auto const_op = shared_cast(op1)) { + unsigned exp = __builtin_ctz(const_op->value); + if (const_op->value == (1U << exp)) { + return const_op; + } + } + else if (auto const_op = shared_cast(op2)) { + unsigned exp = __builtin_ctz(const_op->value); + if (const_op->value == (1U << exp)) { + return const_op; + } + } + return nullptr; + }; + auto _is_const_div_power2 = [&]() -> sptr(ConstantInt) { + if (bin->tag != InstTag::Div) return nullptr; + if (auto const_op = shared_cast(op2)) { + if (const_op->value == (1U << __builtin_ctz(const_op->value))) return const_op; + } + return nullptr; + }; + if (auto const_op = _is_const_mul_power2()) { + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto mc_op = value2moperand(const_op == op1 ? op2 : op1, mc_bb, mp_val2op); + unsigned exp = __builtin_ctz(const_op->value); + auto inst_rsh = MInstBinary::New(MInstTag::Lsh, mc_bb); + inst_rsh->dst = dst; + inst_rsh->op1 = mc_op; + inst_rsh->op2 = MOperand::NewImm(exp); + continue; + } + if (auto const_op = _is_const_div_power2()) { + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op); + unsigned exp = __builtin_ctz(const_op->value); + auto inst_rsh = MInstBinary::New(MInstTag::Rsh, mc_bb); + inst_rsh->dst = dst; + inst_rsh->op1 = mc_op1; + inst_rsh->op2 = MOperand::NewImm(exp); + continue; + } + // no opt for modulo, since they are all signed int, it's wrong + // TODO try to use negative imm to reduce instructions + if (InstTag::Lt <= bin->tag && bin->tag <= InstTag::Ne) { + if (bin->use_list.size() == 1 + && dynamic_cast(bin->use_list.front().user) + && bin->use_list.front().user == (*std::next(bin->inst_itr)).get()) { + // icmp + br, and the result of icmp is only used by that br, merge into single bxx instruction + mp_br2icmp.insert({bin->use_list.front().user, bin}); + continue; + } + else { + LOG(WARNING) << "Condition without branch"; + /* Notes about compare&set: + icmp_slt(r1 < r2) = slt r3, r1, r2 + icmp_sgt(r1 > r2) = slt r3, r2, r1 + icmp_sle(r1 <= r2) = slt r3, r2, r1; xori r3, r3, 1 + icmp_sge(r1 >= r2) = slt r3, r1, r2; xori r3, r3, 1 + icmp_eq(r1 == r2) = xor r3, r1, r2; seqz r3, r3 + icmp_ne(r1 != r2) = xor r3, r1, r2; snez r3, r3 + We can see clearly, though icmp_sge use 1 more inst than icmp_slt, + they involve the same set of registers, so it is okay to defer this to the output stage + */ + } + } + // else if (InstTag::And <= bin->tag && bin->tag <= InstTag::Or) + else { + MInstTag minst_tag; + switch (bin->tag) { + case InstTag::Add: minst_tag = MInstTag::Add; break; + case InstTag::Sub: minst_tag = MInstTag::Sub; break; + case InstTag::Mul: minst_tag = MInstTag::Mul; break; + case InstTag::Div: minst_tag = MInstTag::Div; break; + case InstTag::Mod: minst_tag = MInstTag::Mod; break; + case InstTag::Lt: minst_tag = MInstTag::Lt; break; + case InstTag::Le: minst_tag = MInstTag::Le; break; + case InstTag::Ge: minst_tag = MInstTag::Ge; break; + case InstTag::Gt: minst_tag = MInstTag::Gt; break; + case InstTag::Eq: minst_tag = MInstTag::Eq; break; + case InstTag::Ne: minst_tag = MInstTag::Ne; break; + default: assert(0); + } + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op); + auto mc_op2 = value2moperand(op2, mc_bb, mp_val2op); + auto inst_bin = MInstBinary::New(minst_tag, mc_bb); + inst_bin->dst = dst; + inst_bin->op1 = mc_op1; + inst_bin->op2 = mc_op2; + } + } + else if (auto zxt = shared_cast(inst)) { + // trivial move + auto src = value2moperand(zxt->operand_list[0], mc_bb, mp_val2op); + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto inst_mv = MInstMove::New(mc_bb); + inst_mv->src = src; + inst_mv->dst = dst; + } + } + } + struct pmv { + sptr(MOperand) dst; + sptr(MOperand) src; + }; + // phi elimination: SSA Book Algo 3.6 + // Use some more redundency to save the complicated critical edge split + for (auto ir_bb : func->bb_list) { + auto mc_bb = bb_ir2mc.at(ir_bb); + std::list par_mv_cur; // parallel move in current bb + std::unordered_map par_mv_pred; // parallel move in each pred bb + /* 某个bb的开头有一个phi指令 + %phi_dst = phi [val1 bb1] [val2 bb2] [val3 bb3] ... + 为这东西新建一个虚拟寄存器vr1 + 在当前的bb开头插入 `mv %phi_dst <- %vr1` + 然后在前驱%bb_i的末尾插入 `mv %vr1 <- %val_i` + */ + for (auto inst : ir_bb->inst_list) { + if (!shared_cast(inst)) break; + auto phi = shared_cast(inst); + auto vr = MOperand::NewVirtReg(mc_func->virt_reg_cnt++); + auto dst = value2moperand(inst, mc_bb, mp_val2op); + par_mv_cur.push_back({dst, vr}); + auto pred_itr = phi->parent_bb->pred_list.begin(); + auto val_itr = phi->operand_list.begin(); + // due to sloppy design, pred_bb corresponds in order as incoming val in oplist + for (; val_itr != phi->operand_list.end(); ++pred_itr, ++val_itr) { + auto pred_mc_bb = bb_ir2mc.at(*pred_itr); + auto phi_src_op = value2moperand(*val_itr, pred_mc_bb, mp_val2op); + par_mv_pred.insert({pred_mc_bb, {vr, phi_src_op}}); + } + } + for (auto &pmv : par_mv_cur) { + auto inst_mv = MInstMove::New(mc_bb, true); + inst_mv->src = pmv.src; + inst_mv->dst = pmv.dst; + } + for (auto &pmv_pair : par_mv_pred) { + auto inst_mv = MInstMove::New(pmv_pair.first, true); + inst_mv->src = pmv_pair.second.src; + inst_mv->dst = pmv_pair.second.dst; } } } } -} // namespace codegen \ No newline at end of file +} // namespace CompSysY \ No newline at end of file diff --git a/src/pass_mem2reg.cpp b/src/pass_mem2reg.cpp index 3da947f..5f0b0fc 100644 --- a/src/pass_mem2reg.cpp +++ b/src/pass_mem2reg.cpp @@ -176,7 +176,7 @@ static void _mem_2_reg(FunctionPtr_t func) { 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"); - if (!Type::isType(PointerType::pointedType(ai->type))) continue; + if (!Type::isType(get_pointed_type(ai->type))) continue; alloca_list.push_back(ai); } } @@ -285,7 +285,7 @@ static void _mem_2_reg(FunctionPtr_t func) { continue; } auto ai = Value::as(li->operand_list[0]); - if (!Type::isType(PointerType::pointedType(ai->type))) { + if (!Type::isType(get_pointed_type(ai->type))) { continue; } int alloca_index = alloca_to_id.at(ai); @@ -299,7 +299,7 @@ static void _mem_2_reg(FunctionPtr_t func) { continue; } auto ai = Value::as(si->operand_list[1]); - if (!Type::isType(PointerType::pointedType(ai->type))) { + if (!Type::isType(get_pointed_type(ai->type))) { continue; } int alloca_index = alloca_to_id.at(ai); diff --git a/src/visitor.cpp b/src/visitor.cpp index 6718663..a1e9fa0 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -819,7 +819,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto exp_val = any_to_Value(visitExp(exp_list[i])); ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); } - if (Type::isType(PointerType::pointedType(ptr->type))) { + if (Type::isType(get_pointed_type(ptr->type))) { ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); } return ptr; @@ -869,7 +869,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto exp_val = any_to_Value(visitExp(exp_list[i])); ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); } - if (Type::isType(PointerType::pointedType(ptr->type))) { + if (Type::isType(get_pointed_type(ptr->type))) { ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); } return ptr; diff --git a/src/visitor_factory.cpp b/src/visitor_factory.cpp index 0c627f2..f6e5a3a 100644 --- a/src/visitor_factory.cpp +++ b/src/visitor_factory.cpp @@ -27,9 +27,9 @@ std::shared_ptr build_InstLoad( TypePtr_t type, std::shared_ptr parent_bb ) { - auto inst_load = std::make_shared(value, type, parent_bb); - parent_bb->inst_list.push_back(inst_load); - return inst_load; + 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( @@ -37,9 +37,9 @@ std::shared_ptr build_InstStore( std::shared_ptr pointer, std::shared_ptr parent_bb ) { - auto inst_store = std::make_shared(value, pointer, parent_bb); - parent_bb->inst_list.push_back(inst_store); - return inst_store; + 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 @@ -48,12 +48,12 @@ std::shared_ptr build_InstAlloca( TypePtr_t type, std::shared_ptr parent_bb ) { - auto inst_alloca = std::make_shared(type, parent_bb); - inst_alloca->name = name; + auto inst = std::make_shared(type, parent_bb); + inst->name = name; auto func_head_bb = parent_bb->parent->bb_list.front(); - func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst_alloca); + 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_alloca; + return inst; } std::shared_ptr build_InstBinary( @@ -62,12 +62,12 @@ std::shared_ptr build_InstBinary( std::shared_ptr op2, std::shared_ptr parent_bb ) { - std::shared_ptr inst_binary; - if (InstTag::Lt <= inst_tag && inst_tag <= InstTag::Or) { - inst_binary = std::make_shared(inst_tag, TypeHelper::TYPE_I1, op1, op2, 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_binary = std::make_shared(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb); + inst = std::make_shared(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb); } else { panic("Invalid Binary Operation"); @@ -81,14 +81,14 @@ std::shared_ptr build_InstBinary( assert(0); } } - parent_bb->inst_list.push_back(inst_binary); - return inst_binary; + 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_zext = std::make_shared(op, parent_bb); - parent_bb->inst_list.push_back(inst_zext); - return inst_zext; + 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( @@ -97,26 +97,26 @@ std::shared_ptr build_InstBranch( BasicBlockPtr_t false_block, BasicBlockPtr_t parent_bb ) { - auto inst = std::make_shared(cond, true_block, false_block, parent_bb); - parent_bb->inst_list.push_back(inst); + 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); - parent_bb->inst_list.push_back(inst); + 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); - parent_bb->inst_list.push_back(inst); + 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); - parent_bb->inst_list.push_back(inst); + auto inst = std::make_shared(parent_bb); + inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); return inst; } @@ -125,8 +125,8 @@ std::shared_ptr build_InstCall( const std::vector &args, BasicBlockPtr_t parent_bb ) { - auto inst = std::make_shared(func, args, parent_bb); - parent_bb->inst_list.push_back(inst); + 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; } @@ -135,8 +135,8 @@ std::shared_ptr build_InstGEP( const std::vector &indices, BasicBlockPtr_t parent_bb ) { - auto inst = std::make_shared(pointer, indices, parent_bb); - parent_bb->inst_list.push_back(inst); + 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; } @@ -146,9 +146,9 @@ InstPhiPtr_t build_InstPhi( BasicBlockPtr_t parent_bb, const std::string &name ) { - auto inst = std::make_shared(type, incoming_vals, parent_bb); - inst->name = name; - parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); + 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; } diff --git a/src/visitor_llir_gen.cpp b/src/visitor_llir_gen.cpp index 82c4127..51f2cf6 100644 --- a/src/visitor_llir_gen.cpp +++ b/src/visitor_llir_gen.cpp @@ -21,10 +21,10 @@ std::shared_ptr gen_arr_hierarchy( int base, int length ) { - int dim_n = array_type->element_count; + int dim_n = array_type->elem_count; int dim_size = length / dim_n; std::vector value_list; - if (array_type->element_type->type_tag == Type::TypeTag::IntegerType) { + if (array_type->elem_type->type_tag == Type::TypeTag::IntegerType) { sysy_assert(dim_size == 1); for (int i = 0; i < dim_n; ++i) { if (const_array[base + i]) { @@ -43,7 +43,7 @@ std::shared_ptr gen_arr_hierarchy( int last_non_null = -1; for (int i = 0; i < dim_n; ++i) { auto sub_arr = gen_arr_hierarchy( - std::dynamic_pointer_cast(array_type->element_type), const_array, dim_size * i, dim_size + std::dynamic_pointer_cast(array_type->elem_type), const_array, dim_size * i, dim_size ); value_list.push_back(sub_arr); if (sub_arr) last_non_null = i; @@ -64,7 +64,7 @@ static void _build_arr_init_list( std::shared_ptr arr, std::shared_ptr arr_type ) { - if (arr_type->element_type->type_tag == Type::TypeTag::IntegerType) { + if (arr_type->elem_type->type_tag == Type::TypeTag::IntegerType) { ostr << arr_type->to_IR_string(); ostr << " ["; for (int i = 0; i < arr->value_list.size(); ++i) { @@ -73,7 +73,7 @@ static void _build_arr_init_list( ostr << ", "; } } - for (int i = 0; i < arr_type->element_count - arr->value_list.size(); ++i) { + for (int i = 0; i < arr_type->elem_count - arr->value_list.size(); ++i) { ostr << ", i32 0"; } ostr << "]"; @@ -86,16 +86,16 @@ static void _build_arr_init_list( _build_arr_init_list( ostr, std::dynamic_pointer_cast(arr->value_list[i]), - std::dynamic_pointer_cast(arr_type->element_type) + std::dynamic_pointer_cast(arr_type->elem_type) ); else - ostr << arr_type->element_type->to_IR_string() << " zeroinitializer"; + ostr << arr_type->elem_type->to_IR_string() << " zeroinitializer"; if (i < arr->value_list.size() - 1) { ostr << ", "; } } - for (int i = 0; i < arr_type->element_count - arr->value_list.size(); ++i) { - ostr << ", " << arr_type->element_type->to_IR_string() << " zeroinitializer"; + for (int i = 0; i < arr_type->elem_count - arr->value_list.size(); ++i) { + ostr << ", " << arr_type->elem_type->to_IR_string() << " zeroinitializer"; } ostr << "]"; } @@ -132,8 +132,8 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl case InstTag::Gt: case InstTag::Eq: case InstTag::Ne: - case InstTag::And: - case InstTag::Or: + // case InstTag::And: + // case InstTag::Or: case InstTag::Load: case InstTag::GEP: case InstTag::Alloca: @@ -310,8 +310,8 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl case InstTag::Gt: case InstTag::Eq: case InstTag::Ne: - case InstTag::And: - case InstTag::Or: { + + { auto inst = Value::as(_inst); ostr << "%" << inst->ir_seqno << " = " << inst->tag_string() << " "; if (Value::is(inst->operand_list[0])) {