diff --git a/include/IR/IR_basic.h b/include/IR/IR_basic.h index 3edfa0a..eafab9d 100644 --- a/include/IR/IR_basic.h +++ b/include/IR/IR_basic.h @@ -48,6 +48,7 @@ class TypeDefItem : public LLVMIRItemBase { }; class GlobalVarDefItem : public LLVMIRItemBase { friend class IRBuilder; + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); LLVMType type; std::string name_raw; @@ -66,9 +67,13 @@ class GlobalVarDefItem : public LLVMIRItemBase { } }; class ActionItem : public LLVMIRItemBase {}; -class JMPActionItem : public ActionItem {}; +class JMPActionItem : public ActionItem { + public: + std::shared_ptr corresponding_phi; +}; class BRAction : public JMPActionItem { friend class IRBuilder; + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); std::string cond; std::string true_label_full; std::string false_label_full; @@ -82,6 +87,7 @@ class BRAction : public JMPActionItem { class UNConditionJMPAction : public JMPActionItem { friend class IRBuilder; friend class FunctionDefItem; + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); std::string label_full; public: @@ -91,6 +97,7 @@ class UNConditionJMPAction : public JMPActionItem { class RETAction : public JMPActionItem { friend class IRBuilder; friend class FunctionDefItem; + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); LLVMType type; std::string value; @@ -108,8 +115,12 @@ class RETAction : public JMPActionItem { } } }; +namespace NaiveBackend { +void ScanForVar(class FuncLayout &layout, std::shared_ptr action); +} class BinaryOperationAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string op; std::string operand1_full; std::string operand2_full; @@ -134,6 +145,7 @@ class BinaryOperationAction : public ActionItem { }; class AllocaAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string name_full; LLVMType type; size_t num; @@ -157,6 +169,7 @@ class AllocaAction : public ActionItem { }; class LoadAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string result_full; LLVMType ty; std::string ptr_full; @@ -177,6 +190,7 @@ class LoadAction : public ActionItem { }; class StoreAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); LLVMType ty; std::string value_full; std::string ptr_full; @@ -197,6 +211,7 @@ class StoreAction : public ActionItem { }; class GetElementPtrAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string result_full; LLVMType ty; std::string ptr_full; @@ -224,6 +239,7 @@ class GetElementPtrAction : public ActionItem { }; class ICMPAction : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string op; std::string operand1_full; std::string operand2_full; @@ -247,6 +263,8 @@ class ICMPAction : public ActionItem { 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); std::string label_full; std::vector> actions; std::shared_ptr exit_action; @@ -263,6 +281,7 @@ class BlockItem : public LLVMIRItemBase { }; class CallItem : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string result_full; LLVMType return_type; std::string func_name_raw; @@ -311,6 +330,7 @@ class CallItem : public ActionItem { class PhiItem : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string result_full; LLVMType ty; std::vector> values; // (val_i_full, label_i_full) @@ -337,6 +357,7 @@ class PhiItem : public ActionItem { }; class SelectItem : public ActionItem { friend class IRBuilder; + friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr action); std::string result_full; std::string cond_full; std::string true_val_full; @@ -367,6 +388,7 @@ class SelectItem : public ActionItem { }; class FunctionDefItem : public LLVMIRItemBase { friend class IRBuilder; + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); LLVMType return_type; std::string func_name_raw; std::vector args; @@ -451,6 +473,7 @@ class FunctionDeclareItem : public LLVMIRItemBase { }; class ConstStrItem : public LLVMIRItemBase { friend std::shared_ptr BuildIR(std::shared_ptr src); + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); friend class IRBuilder; std::string string_raw; size_t const_str_id; @@ -484,11 +507,13 @@ class ConstStrItem : public LLVMIRItemBase { class ModuleItem : public LLVMIRItemBase { friend class IRBuilder; friend std::shared_ptr BuildIR(std::shared_ptr src); + friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); std::vector> const_strs; std::vector> function_declares; std::vector> type_defs; std::vector> global_var_defs; std::vector> function_defs; + std::unordered_map low_level_class_info; public: ModuleItem() = default; diff --git a/include/naivebackend/build_layout.hpp b/include/naivebackend/build_layout.hpp new file mode 100644 index 0000000..b0d4894 --- /dev/null +++ b/include/naivebackend/build_layout.hpp @@ -0,0 +1,75 @@ +#pragma once +#include +#include +#include "IR/IR_basic.h" +#include "naivebackend.h" +#include "tools.h" + +namespace NaiveBackend { +inline size_t CalcSize(const LLVMType &tp) { + if (std::holds_alternative(tp)) { + auto &int_tp = std::get(tp); + return (int_tp.bits + 7) / 8; + } else if (std::holds_alternative(tp)) { + return 4; + } else if (std::holds_alternative(tp)) { + throw std::runtime_error("Cannot calculate size of void type"); + return 0; + } else if (std::holds_alternative(tp)) { + throw std::runtime_error("Cannot calculate size of class type"); + } else + throw std::runtime_error("Unknown type"); +} +inline void ScanForVar(FuncLayout &layout, std::shared_ptr action) { + if (std::dynamic_pointer_cast(action)) { + throw std::runtime_error("JMPActionItem should not be in the layout"); + } else if (auto binary_act = std::dynamic_pointer_cast(action)) { + if (binary_act->result_full == "") { + throw std::runtime_error("BinaryOperationAction should have a result_full"); + } + layout.AllocateItem(binary_act->result_full, CalcSize(binary_act->type)); + } else if (auto alloca_act = std::dynamic_pointer_cast(action)) { + if (alloca_act->name_full == "") { + throw std::runtime_error("AllocaAction should have a name_full"); + } + layout.AllocateItem(alloca_act->name_full, CalcSize(alloca_act->type), alloca_act->num); + } else if (auto load_act = std::dynamic_pointer_cast(action)) { + if (load_act->result_full == "") { + throw std::runtime_error("LoadAction should have a result_full"); + } + layout.AllocateItem(load_act->result_full, CalcSize(load_act->ty)); + } else if (auto store_act = std::dynamic_pointer_cast(action)) { + // just do nothing + } else if (auto get_element_act = std::dynamic_pointer_cast(action)) { + if (get_element_act->result_full == "") { + throw std::runtime_error("GetElementPtrAction should have a result_full"); + } + layout.AllocateItem(get_element_act->result_full, CalcSize(get_element_act->ty)); + } else if (auto icmp_act = std::dynamic_pointer_cast(action)) { + if (icmp_act->result_full == "") { + throw std::runtime_error("ICMPAction should have a result_full"); + } + layout.AllocateItem(icmp_act->result_full, 1); + } else if (auto call_act = std::dynamic_pointer_cast(action)) { + if (call_act->result_full == "") { + if (!std::holds_alternative(call_act->return_type)) { + throw std::runtime_error("CallItem should have a result_full"); + } + return; + } + layout.AllocateItem(call_act->result_full, CalcSize(call_act->return_type)); + } else if (auto phi_act = std::dynamic_pointer_cast(action)) { + if (phi_act->result_full == "") { + throw std::runtime_error("PhiItem should have a result_full"); + } + layout.AllocateItem(phi_act->result_full, CalcSize(phi_act->ty)); + } else if (auto select_act = std::dynamic_pointer_cast(action)) { + if (select_act->result_full == "") { + throw std::runtime_error("SelectItem should have a result_full"); + } + layout.AllocateItem(select_act->result_full, CalcSize(select_act->ty)); + } else { + throw std::runtime_error("Unknown action type"); + } +} +} // namespace NaiveBackend \ No newline at end of file diff --git a/include/naivebackend/naivebackend.h b/include/naivebackend/naivebackend.h index 6a46225..9cc1f48 100644 --- a/include/naivebackend/naivebackend.h +++ b/include/naivebackend/naivebackend.h @@ -1,8 +1,12 @@ #pragma once +#include #include #include #include +#include #include +#include +#include #include "IR/IR_basic.h" class RISCVAsmItemBase { public: @@ -11,29 +15,180 @@ class RISCVAsmItemBase { virtual void RecursivePrint(std::ostream &os) const = 0; }; namespace NaiveBackend { - class RISCVConstStrItem : public RISCVAsmItemBase { - public: - RISCVConstStrItem() = default; - ~RISCVConstStrItem() = default; - void RecursivePrint(std::ostream &os) const override; - }; - class RISCVGlobalVarItem : public RISCVAsmItemBase { - public: - RISCVGlobalVarItem() = default; - ~RISCVGlobalVarItem() = default; - void RecursivePrint(std::ostream &os) const override; - }; - class RISCVFuncItem : public RISCVAsmItemBase { - public: - RISCVFuncItem() = default; - ~RISCVFuncItem() = default; - void RecursivePrint(std::ostream &os) const override; - }; - class RISCVProgItem : public RISCVAsmItemBase { - public: - RISCVProgItem() = default; - ~RISCVProgItem() = default; - void RecursivePrint(std::ostream &os) const override; - }; +class RISCVConstStrItem : public RISCVAsmItemBase { + public: + std::string full_label; + std::string content; + RISCVConstStrItem() = default; + ~RISCVConstStrItem() = default; + void RecursivePrint(std::ostream &os) const override { + os << full_label << ":\n"; + os << " .asciz \""; + for (auto c : content) { + if (c == '\n') { + os << "\\n"; + } else if (c == '\t') { + os << "\\t"; + } else if (c == '\"') { + os << "\\\""; + } else { + os << c; + } + } + os << "\"\n"; + } +}; +class RISCVGlobalVarItem : public RISCVAsmItemBase { + public: + std::string full_label; + RISCVGlobalVarItem() = default; + ~RISCVGlobalVarItem() = default; + void RecursivePrint(std::ostream &os) const override { + os << ".globl " << full_label << "\n"; + os << ".p2align 2, 0x0\n"; + os << full_label << ":\n"; + os << " .word 0\n"; + } +}; +class RISCVFuncItem : public RISCVAsmItemBase { + friend void ::GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); + + public: + std::string full_label; + std::vector code_lines; + RISCVFuncItem() = default; + ~RISCVFuncItem() = default; + void RecursivePrint(std::ostream &os) const override { + os << ".globl " << full_label << "\n"; + os << ".p2align 2, 0x0\n"; + os << full_label << ":\n"; + for (auto &line : code_lines) { + os << line << "\n"; + } + } +}; +class RISCVProgItem : public RISCVAsmItemBase { + public: + std::vector> const_strs; + std::vector> global_vars; + std::vector> funcs; + RISCVProgItem() = default; + ~RISCVProgItem() = default; + void RecursivePrint(std::ostream &os) const override { + os << ".section .rodata\n"; + for (auto &item : const_strs) { + item->RecursivePrint(os); + } + os << ".section .sbss\n"; + for (auto &item : global_vars) { + item->RecursivePrint(os); + } + os << ".section .text\n"; + for (auto &item : funcs) { + item->RecursivePrint(os); + } + } +}; +class FuncLayout { + friend void ::GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); + friend void GenerateReadAccess(std::string val, size_t bytes, std::string output_reg, FuncLayout &layout, + std::vector &code_lines); + friend inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout, + std::vector &code_lines); + std::unordered_map local_items; + std::unordered_map arg_offset; + size_t cur_pos; + size_t total_frame_size; // should align to 16 bytes + public: + FuncLayout() : cur_pos(8), total_frame_size(16) {} + void AllocateItem(const std::string &name, size_t sz, size_t num = 1) { + if (local_items.find(name) != local_items.end()) throw std::runtime_error("Local item already exists"); + if (cur_pos % sz != 0) { + cur_pos += sz - cur_pos % sz; + } + cur_pos += sz * num; + local_items[name] = cur_pos; + total_frame_size = ((cur_pos + 15) / 16) * 16; + std::cerr << "allocating stack memory for " << name << " at " << cur_pos << std::endl; + } + size_t QueryOffeset(const std::string &name) { + if (local_items.find(name) == local_items.end()) throw std::runtime_error("Local item not found"); + return local_items[name]; + } + size_t QueryFrameSize() const { return total_frame_size; } +}; + +inline void GenerateReadAccess(std::string val, size_t bytes, std::string output_reg, FuncLayout &layout, + std::vector &code_lines) { + if (val.size() > 4 && val.substr(val.size() - 4, 4) == ".val") { + // parameter + if (layout.arg_offset.find(val) == layout.arg_offset.end()) { + throw std::runtime_error("Unknown argument with name=" + val); + } + size_t offset = layout.arg_offset.at(val); + if (offset < 8) { + output_reg = "a" + std::to_string(offset); + } else { + size_t spilled_offset = (offset - 8) * 4; // just*4, which is different from the real riscv + std::string cmd; + if (bytes == 1) + cmd = "lb"; + else if (bytes == 4) + cmd = "lw"; + else + throw std::runtime_error("Unknown bytes"); + cmd += " " + output_reg + ", " + std::to_string(spilled_offset) + "(fp)"; + code_lines.push_back(cmd); + } + } else if (val.size() > 13 && val.substr(0, 13) == "@.var.global.") { + // global variable address keeper + std::string label_in_asm = val.substr(1, val.size() - 1); + code_lines.push_back("la " + output_reg + ", " + label_in_asm); + } else if (val.size() > 12 && val.substr(0, 12) == "%.var.local.") { + // local variable address keeper + size_t offset = layout.QueryOffeset(val); + code_lines.push_back("addi " + output_reg + ", fp, -" + std::to_string(offset)); + } else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") { + // tmp variable, not address keeper + size_t offset = layout.QueryOffeset(val); + code_lines.push_back("addi " + output_reg + ", fp, -" + std::to_string(offset)); + if (bytes == 1) { + code_lines.push_back("lb " + output_reg + ", 0(" + output_reg + ")"); + } else if (bytes == 4) { + code_lines.push_back("lw " + output_reg + ", 0(" + output_reg + ")"); + } else { + throw std::runtime_error("Unknown bytes"); + } + } else { + throw std::runtime_error("Unknown variable type with name=" + val); + } } +inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout, + std::vector &code_lines) { + if (val.size() > 4 && val.substr(val.size() - 4, 4) == ".val") { + // parameter + throw std::runtime_error("Cannot write to a parameter"); + } else if (val.size() > 13 && val.substr(0, 13) == "@.var.global.") { + // global variable address keeper + throw std::runtime_error("Cannot write to a global variable address keeper"); + } else if (val.size() > 12 && val.substr(0, 12) == "%.var.local.") { + // local variable address keeper + throw std::runtime_error("Cannot write to a local variable address keeper"); + } else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") { + // tmp variable, not address keeper + size_t offset = layout.QueryOffeset(val); + code_lines.push_back("addi " + data_reg + ", fp, -" + std::to_string(offset)); + if (bytes == 1) { + code_lines.push_back("sb " + data_reg + ", 0(" + data_reg + ")"); + } else if (bytes == 4) { + code_lines.push_back("sw " + data_reg + ", 0(" + data_reg + ")"); + } else { + throw std::runtime_error("Unknown bytes"); + } + } else { + throw std::runtime_error("Unknown variable type with name=" + val); + } +} +} // namespace NaiveBackend + void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog); \ No newline at end of file diff --git a/src/IR/IRBuilder.cpp b/src/IR/IRBuilder.cpp index 73d254d..d3af6ab 100644 --- a/src/IR/IRBuilder.cpp +++ b/src/IR/IRBuilder.cpp @@ -72,9 +72,9 @@ void IRBuilder::ActuralVisit(FuncDef_ASTNode *node) { std::dynamic_pointer_cast(cur_func->init_block->exit_action)->label_full = current_block->label_full; is_in_func_def = true; - cur_alloca_block=func_def->init_block; + cur_alloca_block = func_def->init_block; node->func_body->accept(this); - cur_alloca_block=main_init_block; + cur_alloca_block = main_init_block; is_in_func_def = false; if (!(cur_block->exit_action)) { @@ -92,6 +92,7 @@ void IRBuilder::ActuralVisit(FuncDef_ASTNode *node) { void IRBuilder::ActuralVisit(ClassDef_ASTNode *node) { is_in_class_def = true; cur_class_name = node->class_name; + prog->low_level_class_info["%.class." + cur_class_name] = global_scope->fetch_class_info(cur_class_name); auto tpdf = std::make_shared(); tpdf->class_name_raw = node->class_name; cur_class = tpdf; @@ -103,7 +104,7 @@ void IRBuilder::ActuralVisit(ClassDef_ASTNode *node) { } void IRBuilder::ActuralVisit(Program_ASTNode *node) { - cur_alloca_block=main_init_block; + cur_alloca_block = main_init_block; for (auto ch : node->sorted_children) { ch->accept(this); } @@ -950,6 +951,8 @@ void IRBuilder::ActuralVisit(LAndExpr_ASTNode *node) { size_t new_block_id = block_counter++; auto right_cal_block = std::make_shared(); auto new_block = std::make_shared(); + auto phi_act = std::make_shared(); + right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id); new_block->label_full = "label_" + std::to_string(new_block_id); cur_block->exit_action = std::make_shared(); @@ -957,15 +960,18 @@ void IRBuilder::ActuralVisit(LAndExpr_ASTNode *node) { std::dynamic_pointer_cast(cur_block->exit_action)->true_label_full = right_cal_block->label_full; std::dynamic_pointer_cast(cur_block->exit_action)->false_label_full = new_block->label_full; std::dynamic_pointer_cast(cur_block->exit_action)->cond = node->left->IR_result_full; + cur_block->exit_action->corresponding_phi = phi_act; + cur_func->basic_blocks.push_back(right_cal_block); cur_block = right_cal_block; node->right->accept(this); cur_block->exit_action = std::make_shared(); auto right_block_end = cur_block; std::dynamic_pointer_cast(cur_block->exit_action)->label_full = new_block->label_full; + cur_block->exit_action->corresponding_phi = phi_act; + cur_func->basic_blocks.push_back(new_block); cur_block = new_block; - auto phi_act = std::make_shared(); phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++); phi_act->ty = LLVMIRIntType(1); phi_act->values.push_back(std::make_pair("0", src_block->label_full)); @@ -989,6 +995,8 @@ void IRBuilder::ActuralVisit(LOrExpr_ASTNode *node) { size_t new_block_id = block_counter++; auto right_cal_block = std::make_shared(); auto new_block = std::make_shared(); + auto phi_act = std::make_shared(); + right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id); new_block->label_full = "label_" + std::to_string(new_block_id); cur_block->exit_action = std::make_shared(); @@ -996,15 +1004,18 @@ void IRBuilder::ActuralVisit(LOrExpr_ASTNode *node) { std::dynamic_pointer_cast(cur_block->exit_action)->true_label_full = new_block->label_full; std::dynamic_pointer_cast(cur_block->exit_action)->false_label_full = right_cal_block->label_full; std::dynamic_pointer_cast(cur_block->exit_action)->cond = node->left->IR_result_full; + cur_block->exit_action->corresponding_phi = phi_act; + cur_func->basic_blocks.push_back(right_cal_block); cur_block = right_cal_block; node->right->accept(this); cur_block->exit_action = std::make_shared(); auto right_block_end = cur_block; std::dynamic_pointer_cast(cur_block->exit_action)->label_full = new_block->label_full; + cur_block->exit_action->corresponding_phi = phi_act; + cur_func->basic_blocks.push_back(new_block); cur_block = new_block; - auto phi_act = std::make_shared(); phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++); phi_act->ty = LLVMIRIntType(1); phi_act->values.push_back(std::make_pair("1", src_block->label_full)); @@ -1045,6 +1056,8 @@ void IRBuilder::ActuralVisit(TernaryExpr_ASTNode *node) { ExprTypeInfo void_std = IdentifierType("void"); if (node->expr_type_info != void_std) { auto phi_act = std::make_shared(); + src1_end_block->exit_action->corresponding_phi = phi_act; + src2_end_block->exit_action->corresponding_phi = phi_act; phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++); phi_act->ty = Type_AST2LLVM(node->expr_type_info); phi_act->values.push_back(std::make_pair(node->src1->IR_result_full, src1_end_block->label_full)); diff --git a/src/main.cpp b/src/main.cpp index 85b2e36..d19208a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,8 +28,8 @@ int main(int argc, char **argv) { try { SemanticCheck(fin, ast); auto IR = BuildIR(ast); - IR->RecursivePrint(fout); - // GenerateNaiveASM(fout, IR); + IR->RecursivePrint(std::cerr); + GenerateNaiveASM(fout, IR); } catch (const SemanticError &err) { std::cout << err.what() << std::endl; return err.GetErrorCode(); diff --git a/src/naivebackend/naivebackend.cpp b/src/naivebackend/naivebackend.cpp index 0a571dc..fd26048 100644 --- a/src/naivebackend/naivebackend.cpp +++ b/src/naivebackend/naivebackend.cpp @@ -1,4 +1,59 @@ #include "naivebackend.h" +#include +#include "IR/IR_basic.h" +#include "build_layout.hpp" +using namespace NaiveBackend; void GenerateNaiveASM(std::ostream &os, std::shared_ptr prog) { - ; + auto riscv = std::make_shared(); + + for (auto conststr : prog->const_strs) { + auto asm_item = std::make_shared(); + riscv->const_strs.push_back(asm_item); + asm_item->content = conststr->string_raw; + asm_item->full_label = ".str." + std::to_string(conststr->const_str_id); + } + for (auto global_var : prog->global_var_defs) { + auto asm_item = std::make_shared(); + riscv->global_vars.push_back(asm_item); + asm_item->full_label = ".var.global." + global_var->name_raw + ".addrkp"; + } + std::unordered_map func_layouts; + for (auto func_def : prog->function_defs) { + if (func_def->init_block) { + for (auto act : func_def->init_block->actions) { + ScanForVar(func_layouts[func_def->func_name_raw], act); + } + } + for (auto block : func_def->basic_blocks) { + for (auto act : block->actions) { + ScanForVar(func_layouts[func_def->func_name_raw], act); + } + } + FuncLayout &layout = func_layouts[func_def->func_name_raw]; + for (size_t i = 0; i < func_def->args_full_name.size(); i++) { + layout.arg_offset[func_def->args_full_name[i]] = i; + } + // debug: + + std::cerr << "layout info of function " << func_def->func_name_raw << std::endl; + std::cerr << "\tcur_pos=" << layout.cur_pos << std::endl; + std::cerr << "\ttotal_frame_size=" << layout.total_frame_size << std::endl; + for (const auto &item : layout.local_items) { + std::cerr << "\t" << item.first << " " << item.second << std::endl; + } + } + + for (auto func_def : prog->function_defs) { + auto func_asm = std::make_shared(); + riscv->funcs.push_back(func_asm); + func_asm->full_label = func_def->func_name_raw; + if (func_def->init_block) { + func_asm->code_lines.push_back(".entrylabel." + func_def->init_block->label_full + ":"); + } + for (auto block : func_def->basic_blocks) { + func_asm->code_lines.push_back(".entrylabel." + block->label_full + ":"); + } + } + + riscv->RecursivePrint(os); } \ No newline at end of file