diff --git a/include/IR/IR_basic.h b/include/IR/IR_basic.h index 6de3ffd..caf3f46 100644 --- a/include/IR/IR_basic.h +++ b/include/IR/IR_basic.h @@ -72,7 +72,8 @@ class JMPActionItem : public ActionItem { std::shared_ptr corresponding_phi; }; namespace NaiveBackend { -void ScanForVar(class FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); +void ScanForVar(class FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); void GenerateASM(std::shared_ptr act, std::vector &code_lines, FuncLayout &layout, const std::unordered_map &low_level_class_info, bool process_phi); } // namespace NaiveBackend @@ -135,7 +136,8 @@ class RETAction : public JMPActionItem { class BinaryOperationAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, NaiveBackend::FuncLayout &layout, const std::unordered_map &low_level_class_info, @@ -164,7 +166,8 @@ class BinaryOperationAction : public ActionItem { }; class AllocaAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); std::string name_full; LLVMType type; size_t num; @@ -188,7 +191,8 @@ class AllocaAction : public ActionItem { }; class LoadAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, NaiveBackend::FuncLayout &layout, const std::unordered_map &low_level_class_info, @@ -213,7 +217,8 @@ class LoadAction : public ActionItem { }; class StoreAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, NaiveBackend::FuncLayout &layout, const std::unordered_map &low_level_class_info, @@ -238,7 +243,12 @@ class StoreAction : public ActionItem { }; class GetElementPtrAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); + friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, + NaiveBackend::FuncLayout &layout, + const std::unordered_map &low_level_class_info, + bool process_phi); std::string result_full; LLVMType ty; std::string ptr_full; @@ -266,7 +276,8 @@ class GetElementPtrAction : public ActionItem { }; class ICMPAction : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, NaiveBackend::FuncLayout &layout, const std::unordered_map &low_level_class_info, @@ -295,7 +306,8 @@ class BlockItem : public LLVMIRItemBase { friend class IRBuilder; friend class FunctionDefItem; friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); std::string label_full; std::vector> actions; std::shared_ptr exit_action; @@ -312,7 +324,8 @@ class BlockItem : public LLVMIRItemBase { }; class CallItem : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, NaiveBackend::FuncLayout &layout, const std::unordered_map &low_level_class_info, @@ -365,7 +378,12 @@ class CallItem : public ActionItem { class PhiItem : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); + friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, + NaiveBackend::FuncLayout &layout, + const std::unordered_map &low_level_class_info, + bool process_phi); std::string result_full; LLVMType ty; std::vector> values; // (val_i_full, label_i_full) @@ -392,7 +410,12 @@ class PhiItem : public ActionItem { }; class SelectItem : public ActionItem { friend class IRBuilder; - friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, const std::unordered_map &low_level_class_info); + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action, + const std::unordered_map &low_level_class_info); + friend void NaiveBackend::GenerateASM(std::shared_ptr act, std::vector &code_lines, + NaiveBackend::FuncLayout &layout, + const std::unordered_map &low_level_class_info, + bool process_phi); std::string result_full; std::string cond_full; std::string true_val_full; diff --git a/include/naivebackend/build_layout.hpp b/include/naivebackend/build_layout.hpp index cd32276..2982fdc 100644 --- a/include/naivebackend/build_layout.hpp +++ b/include/naivebackend/build_layout.hpp @@ -39,8 +39,7 @@ inline void ScanForVar(FuncLayout &layout, std::shared_ptr action, size_t element_idx = std::stoi(get_element_act->indices[1]); auto class_ty = std::get(get_element_act->ty); const IRClassInfo &class_info = low_level_class_info.at(class_ty.class_name_full); - size_t sz = class_info.member_var_size[element_idx]; - layout.AllocateItem(get_element_act->result_full, sz); + layout.AllocateItem(get_element_act->result_full, 4); } else { throw std::runtime_error("GetElementPtrAction with more than 2 indices is not supported"); } diff --git a/include/naivebackend/codegen.hpp b/include/naivebackend/codegen.hpp index 0f7277a..0ee32fd 100644 --- a/include/naivebackend/codegen.hpp +++ b/include/naivebackend/codegen.hpp @@ -1,7 +1,10 @@ #pragma once +#include #include #include "naivebackend.h" +#include "tools.h" namespace NaiveBackend { +extern std::string cur_block_label_for_phi; inline void GenerateASM(std::shared_ptr act, std::vector &code_lines, FuncLayout &layout, const std::unordered_map &low_level_class_info, bool process_phi = false) { @@ -73,7 +76,29 @@ inline void GenerateASM(std::shared_ptr act, std::vector(act)) { - // TODO: implement this + if (get_element_act->indices.size() == 1) { + // array access + IRVar2RISCVReg(get_element_act->ptr_full, 4, "t0", layout, code_lines); + IRVar2RISCVReg(get_element_act->indices[0], 4, "t1", layout, code_lines); + size_t element_sz = CalcSize(get_element_act->ty); + code_lines.push_back("slli t1, t1, " + std::to_string(std::countr_zero(element_sz))); + code_lines.push_back("add t2, t0, t1"); + GenerateWriteAccess(get_element_act->result_full, element_sz, "t2", layout, code_lines); + } else if (get_element_act->indices.size() == 2) { + // struct access + if (get_element_act->indices[0] != "0") { + throw std::runtime_error("struct access with non-zero offset is not supported"); + } + size_t element_idx = std::stoull(get_element_act->indices[1]); + auto class_ty = std::get(get_element_act->ty); + const IRClassInfo &class_info = low_level_class_info.at(class_ty.class_name_full); + size_t offset = class_info.member_var_pos_after_align[element_idx]; + IRVar2RISCVReg(get_element_act->ptr_full, 4, "t0", layout, code_lines); + code_lines.push_back("addi t2, t0, " + std::to_string(offset)); + GenerateWriteAccess(get_element_act->result_full, 4, "t2", layout, code_lines); + } else { + throw std::runtime_error("Unknown getelementptr indices size"); + } } else if (auto icmp_act = std::dynamic_pointer_cast(act)) { size_t sz = CalcSize(icmp_act->type); IRVar2RISCVReg(icmp_act->operand1_full, sz, "t0", layout, code_lines); @@ -124,11 +149,33 @@ inline void GenerateASM(std::shared_ptr act, std::vectorvalues) { + if (label == self_label) { + size_t sz = CalcSize(phi_act->ty); + IRVar2RISCVReg(val, sz, "t0", layout, code_lines); + GenerateWriteAccess(phi_act->result_full, sz, "t0", layout, code_lines); + return; + } + } + throw std::runtime_error("cannot found label for phi action"); } else if (auto select_act = std::dynamic_pointer_cast(act)) { - // TODO: implement this - // throw std::runtime_error("not implemented"); + LLVMType ty_int32 = LLVMIRIntType(32); + LLVMType ty_ptr = LLVMIRPTRType(); + if (select_act->ty != ty_int32 && select_act->ty != ty_ptr) { + throw std::runtime_error("select action only support int32 or ptr"); + } + IRVar2RISCVReg(select_act->cond_full, 1, "t0", layout, code_lines); + IRVar2RISCVReg(select_act->true_val_full, 4, "t1", layout, code_lines); + IRVar2RISCVReg(select_act->false_val_full, 4, "t2", layout, code_lines); + // use binary operation to implement select for efficiency + code_lines.push_back("slli t0, t0, 31"); + code_lines.push_back("srai t0, t0, 31"); + code_lines.push_back("and t1, t0, t1"); + code_lines.push_back("not t0, t0"); + code_lines.push_back("and t2, t0, t2"); + code_lines.push_back("or t0, t1, t2"); + GenerateWriteAccess(select_act->result_full, 4, "t0", layout, code_lines); } else { throw std::runtime_error("Unknown action type"); } diff --git a/include/naivebackend/naivebackend.h b/include/naivebackend/naivebackend.h index 619e5f7..95c2bae 100644 --- a/include/naivebackend/naivebackend.h +++ b/include/naivebackend/naivebackend.h @@ -165,7 +165,7 @@ inline void GenerateReadAccess(std::string val, size_t bytes, std::string output throw std::runtime_error("Unknown bytes"); } } else if (val.size() > 6 && val.substr(0, 6) == "@.str.") { - code_lines.push_back("la " + output_reg.substr(1, output_reg.size() - 1) + ", " + val); + code_lines.push_back("la " + output_reg + ", " + val.substr(1, val.size() - 1)); } else { throw std::runtime_error("Unknown variable type with name=" + val); } diff --git a/include/tools.h b/include/tools.h index df51a49..ee7b96c 100644 --- a/include/tools.h +++ b/include/tools.h @@ -108,11 +108,17 @@ class LLVMIRIntType { size_t bits; LLVMIRIntType() = default; LLVMIRIntType(size_t bits) : bits(bits) {} + bool operator==(const LLVMIRIntType &r) const { return bits == r.bits; } +}; +struct LLVMIRPTRType { + bool operator==(const LLVMIRPTRType &r) const { return true; } +}; +struct LLVMVOIDType { + bool operator==(const LLVMVOIDType &r) const { return true; } }; -struct LLVMIRPTRType {}; -struct LLVMVOIDType {}; struct LLVMIRCLASSTYPE { std::string class_name_full; + bool operator==(const LLVMIRCLASSTYPE &r) const { return class_name_full == r.class_name_full; } }; using LLVMType = std::variant; class IRClassInfo { diff --git a/src/naivebackend/naivebackend.cpp b/src/naivebackend/naivebackend.cpp index b73d08b..6baeeec 100644 --- a/src/naivebackend/naivebackend.cpp +++ b/src/naivebackend/naivebackend.cpp @@ -3,6 +3,9 @@ #include "IR/IR_basic.h" #include "build_layout.hpp" #include "codegen.hpp" +namespace NaiveBackend { +std::string cur_block_label_for_phi; +} using namespace NaiveBackend; void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog) { auto riscv = std::make_shared(); @@ -60,6 +63,7 @@ void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog) { prog->low_level_class_info); } if (func_def->init_block->exit_action->corresponding_phi) { + NaiveBackend::cur_block_label_for_phi = func_def->init_block->label_full; NaiveBackend::GenerateASM(func_def->init_block->exit_action->corresponding_phi, func_asm->code_lines, func_layouts[func_def->func_name_raw], prog->low_level_class_info, true); } @@ -73,6 +77,7 @@ void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog) { prog->low_level_class_info); } if (block->exit_action->corresponding_phi) { + NaiveBackend::cur_block_label_for_phi = block->label_full; NaiveBackend::GenerateASM(block->exit_action->corresponding_phi, func_asm->code_lines, func_layouts[func_def->func_name_raw], prog->low_level_class_info, true); }