basically write codegen
This commit is contained in:
5
Makefile
5
Makefile
@ -12,9 +12,10 @@ build:
|
|||||||
@cd $(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -Wno-dev ..
|
@cd $(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -Wno-dev ..
|
||||||
@cd $(BUILD_DIR) && $(MAKE) -j4
|
@cd $(BUILD_DIR) && $(MAKE) -j4
|
||||||
|
|
||||||
# 运行目标,运行生成的可执行文件
|
acturalrun:
|
||||||
run:
|
|
||||||
@cd $(BUILD_DIR) && ./zmxcc /dev/stdin -o /dev/stdout 2>/dev/null
|
@cd $(BUILD_DIR) && ./zmxcc /dev/stdin -o /dev/stdout 2>/dev/null
|
||||||
|
# 运行目标,运行生成的可执行文件
|
||||||
|
run: acturalrun
|
||||||
@cat $(BUILTIN_ASM) >>/dev/stdout
|
@cat $(BUILTIN_ASM) >>/dev/stdout
|
||||||
|
|
||||||
# 清理目标
|
# 清理目标
|
||||||
|
@ -71,9 +71,18 @@ class JMPActionItem : public ActionItem {
|
|||||||
public:
|
public:
|
||||||
std::shared_ptr<class PhiItem> corresponding_phi;
|
std::shared_ptr<class PhiItem> corresponding_phi;
|
||||||
};
|
};
|
||||||
|
namespace NaiveBackend {
|
||||||
|
void ScanForVar(class FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
void GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines, FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info, bool process_phi);
|
||||||
|
} // namespace NaiveBackend
|
||||||
class BRAction : public JMPActionItem {
|
class BRAction : public JMPActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string cond;
|
std::string cond;
|
||||||
std::string true_label_full;
|
std::string true_label_full;
|
||||||
std::string false_label_full;
|
std::string false_label_full;
|
||||||
@ -88,6 +97,10 @@ class UNConditionJMPAction : public JMPActionItem {
|
|||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend class FunctionDefItem;
|
friend class FunctionDefItem;
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string label_full;
|
std::string label_full;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -98,6 +111,10 @@ class RETAction : public JMPActionItem {
|
|||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend class FunctionDefItem;
|
friend class FunctionDefItem;
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
LLVMType type;
|
LLVMType type;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
@ -115,12 +132,14 @@ class RETAction : public JMPActionItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
namespace NaiveBackend {
|
|
||||||
void ScanForVar(class FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
|
||||||
}
|
|
||||||
class BinaryOperationAction : public ActionItem {
|
class BinaryOperationAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string op;
|
std::string op;
|
||||||
std::string operand1_full;
|
std::string operand1_full;
|
||||||
std::string operand2_full;
|
std::string operand2_full;
|
||||||
@ -145,7 +164,7 @@ class BinaryOperationAction : public ActionItem {
|
|||||||
};
|
};
|
||||||
class AllocaAction : public ActionItem {
|
class AllocaAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
std::string name_full;
|
std::string name_full;
|
||||||
LLVMType type;
|
LLVMType type;
|
||||||
size_t num;
|
size_t num;
|
||||||
@ -169,7 +188,11 @@ class AllocaAction : public ActionItem {
|
|||||||
};
|
};
|
||||||
class LoadAction : public ActionItem {
|
class LoadAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -190,7 +213,11 @@ class LoadAction : public ActionItem {
|
|||||||
};
|
};
|
||||||
class StoreAction : public ActionItem {
|
class StoreAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string value_full;
|
std::string value_full;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -211,7 +238,7 @@ class StoreAction : public ActionItem {
|
|||||||
};
|
};
|
||||||
class GetElementPtrAction : public ActionItem {
|
class GetElementPtrAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -239,7 +266,11 @@ class GetElementPtrAction : public ActionItem {
|
|||||||
};
|
};
|
||||||
class ICMPAction : public ActionItem {
|
class ICMPAction : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string op;
|
std::string op;
|
||||||
std::string operand1_full;
|
std::string operand1_full;
|
||||||
std::string operand2_full;
|
std::string operand2_full;
|
||||||
@ -264,7 +295,7 @@ class BlockItem : public LLVMIRItemBase {
|
|||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend class FunctionDefItem;
|
friend class FunctionDefItem;
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
std::string label_full;
|
std::string label_full;
|
||||||
std::vector<std::shared_ptr<ActionItem>> actions;
|
std::vector<std::shared_ptr<ActionItem>> actions;
|
||||||
std::shared_ptr<JMPActionItem> exit_action;
|
std::shared_ptr<JMPActionItem> exit_action;
|
||||||
@ -281,7 +312,11 @@ class BlockItem : public LLVMIRItemBase {
|
|||||||
};
|
};
|
||||||
class CallItem : public ActionItem {
|
class CallItem : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
NaiveBackend::FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType return_type;
|
LLVMType return_type;
|
||||||
std::string func_name_raw;
|
std::string func_name_raw;
|
||||||
@ -330,7 +365,7 @@ class CallItem : public ActionItem {
|
|||||||
|
|
||||||
class PhiItem : public ActionItem {
|
class PhiItem : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::vector<std::pair<std::string, std::string>> values; // (val_i_full, label_i_full)
|
std::vector<std::pair<std::string, std::string>> values; // (val_i_full, label_i_full)
|
||||||
@ -357,7 +392,7 @@ class PhiItem : public ActionItem {
|
|||||||
};
|
};
|
||||||
class SelectItem : public ActionItem {
|
class SelectItem : public ActionItem {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
friend void NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action, const std::unordered_map<std::string, IRClassInfo> &low_level_class_info);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
std::string cond_full;
|
std::string cond_full;
|
||||||
std::string true_val_full;
|
std::string true_val_full;
|
||||||
|
@ -6,21 +6,8 @@
|
|||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
namespace NaiveBackend {
|
namespace NaiveBackend {
|
||||||
inline size_t CalcSize(const LLVMType &tp) {
|
inline void ScanForVar(FuncLayout &layout, std::shared_ptr<ActionItem> action,
|
||||||
if (std::holds_alternative<LLVMIRIntType>(tp)) {
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info) {
|
||||||
auto &int_tp = std::get<LLVMIRIntType>(tp);
|
|
||||||
return (int_tp.bits + 7) / 8;
|
|
||||||
} else if (std::holds_alternative<LLVMIRPTRType>(tp)) {
|
|
||||||
return 4;
|
|
||||||
} else if (std::holds_alternative<LLVMVOIDType>(tp)) {
|
|
||||||
throw std::runtime_error("Cannot calculate size of void type");
|
|
||||||
return 0;
|
|
||||||
} else if (std::holds_alternative<LLVMIRCLASSTYPE>(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<ActionItem> action) {
|
|
||||||
if (std::dynamic_pointer_cast<JMPActionItem>(action)) {
|
if (std::dynamic_pointer_cast<JMPActionItem>(action)) {
|
||||||
throw std::runtime_error("JMPActionItem should not be in the layout");
|
throw std::runtime_error("JMPActionItem should not be in the layout");
|
||||||
} else if (auto binary_act = std::dynamic_pointer_cast<BinaryOperationAction>(action)) {
|
} else if (auto binary_act = std::dynamic_pointer_cast<BinaryOperationAction>(action)) {
|
||||||
@ -44,7 +31,19 @@ inline void ScanForVar(FuncLayout &layout, std::shared_ptr<ActionItem> action) {
|
|||||||
if (get_element_act->result_full == "") {
|
if (get_element_act->result_full == "") {
|
||||||
throw std::runtime_error("GetElementPtrAction should have a result_full");
|
throw std::runtime_error("GetElementPtrAction should have a result_full");
|
||||||
}
|
}
|
||||||
layout.AllocateItem(get_element_act->result_full, CalcSize(get_element_act->ty));
|
if (get_element_act->indices.size() == 1) {
|
||||||
|
layout.AllocateItem(get_element_act->result_full, CalcSize(get_element_act->ty));
|
||||||
|
} else if (get_element_act->indices.size() == 2) {
|
||||||
|
if (get_element_act->indices[0] != "0")
|
||||||
|
throw std::runtime_error("GetElementPtrAction with non-zero base index is not supported");
|
||||||
|
size_t element_idx = std::stoi(get_element_act->indices[1]);
|
||||||
|
auto class_ty = std::get<LLVMIRCLASSTYPE>(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);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("GetElementPtrAction with more than 2 indices is not supported");
|
||||||
|
}
|
||||||
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(action)) {
|
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(action)) {
|
||||||
if (icmp_act->result_full == "") {
|
if (icmp_act->result_full == "") {
|
||||||
throw std::runtime_error("ICMPAction should have a result_full");
|
throw std::runtime_error("ICMPAction should have a result_full");
|
||||||
|
136
include/naivebackend/codegen.hpp
Normal file
136
include/naivebackend/codegen.hpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "naivebackend.h"
|
||||||
|
namespace NaiveBackend {
|
||||||
|
inline void GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines, FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi = false) {
|
||||||
|
if (auto br_act = std::dynamic_pointer_cast<BRAction>(act)) {
|
||||||
|
IRVar2RISCVReg(br_act->cond, 1, "t0", layout, code_lines);
|
||||||
|
code_lines.push_back("bnez t0, .entrylabel." + br_act->true_label_full);
|
||||||
|
code_lines.push_back("j .entrylabel." + br_act->false_label_full);
|
||||||
|
} else if (auto jmp_act = std::dynamic_pointer_cast<UNConditionJMPAction>(act)) {
|
||||||
|
code_lines.push_back("j .entrylabel." + jmp_act->label_full);
|
||||||
|
} else if (auto ret_act = std::dynamic_pointer_cast<RETAction>(act)) {
|
||||||
|
if (!std::holds_alternative<LLVMVOIDType>(ret_act->type)) {
|
||||||
|
size_t sz = CalcSize(ret_act->type);
|
||||||
|
IRVar2RISCVReg(ret_act->value, sz, "a0", layout, code_lines);
|
||||||
|
}
|
||||||
|
code_lines.push_back("lw ra, -4(s0)");
|
||||||
|
code_lines.push_back("lw s0, -8(s0)");
|
||||||
|
code_lines.push_back("addi sp, sp, " + std::to_string(layout.total_frame_size));
|
||||||
|
code_lines.push_back("ret");
|
||||||
|
} else if (auto binary_act = std::dynamic_pointer_cast<BinaryOperationAction>(act)) {
|
||||||
|
size_t sz = CalcSize(binary_act->type);
|
||||||
|
IRVar2RISCVReg(binary_act->operand1_full, sz, "t0", layout, code_lines);
|
||||||
|
IRVar2RISCVReg(binary_act->operand2_full, sz, "t1", layout, code_lines);
|
||||||
|
if (binary_act->op == "add") {
|
||||||
|
code_lines.push_back("add t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "sub") {
|
||||||
|
code_lines.push_back("sub t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "mul") {
|
||||||
|
code_lines.push_back("mul t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "sdiv") {
|
||||||
|
code_lines.push_back("div t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "srem") {
|
||||||
|
code_lines.push_back("rem t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "and") {
|
||||||
|
code_lines.push_back("and t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "or") {
|
||||||
|
code_lines.push_back("or t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "xor") {
|
||||||
|
code_lines.push_back("xor t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "shl") {
|
||||||
|
code_lines.push_back("sll t2, t0, t1");
|
||||||
|
} else if (binary_act->op == "ashr") {
|
||||||
|
code_lines.push_back("sra t2, t0, t1");
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown binary operation");
|
||||||
|
}
|
||||||
|
GenerateWriteAccess(binary_act->result_full, sz, "t2", layout, code_lines);
|
||||||
|
} else if (auto alloca_act = std::dynamic_pointer_cast<AllocaAction>(act)) {
|
||||||
|
// just do nothing
|
||||||
|
} else if (auto load_act = std::dynamic_pointer_cast<LoadAction>(act)) {
|
||||||
|
size_t sz = CalcSize(load_act->ty);
|
||||||
|
IRVar2RISCVReg(load_act->ptr_full, 4, "t0", layout, code_lines);
|
||||||
|
if (sz == 1) {
|
||||||
|
code_lines.push_back("lb t1, 0(t0)");
|
||||||
|
} else if (sz == 4) {
|
||||||
|
code_lines.push_back("lw t1, 0(t0)");
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown bytes");
|
||||||
|
}
|
||||||
|
GenerateWriteAccess(load_act->result_full, sz, "t1", layout, code_lines);
|
||||||
|
} else if (auto store_act = std::dynamic_pointer_cast<StoreAction>(act)) {
|
||||||
|
size_t sz = CalcSize(store_act->ty);
|
||||||
|
IRVar2RISCVReg(store_act->ptr_full, 4, "t0", layout, code_lines);
|
||||||
|
IRVar2RISCVReg(store_act->value_full, sz, "t1", layout, code_lines);
|
||||||
|
if (sz == 1) {
|
||||||
|
code_lines.push_back("sb t1, 0(t0)");
|
||||||
|
} else if (sz == 4) {
|
||||||
|
code_lines.push_back("sw t1, 0(t0)");
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown bytes");
|
||||||
|
}
|
||||||
|
} else if (auto get_element_act = std::dynamic_pointer_cast<GetElementPtrAction>(act)) {
|
||||||
|
// TODO: implement this
|
||||||
|
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(act)) {
|
||||||
|
size_t sz = CalcSize(icmp_act->type);
|
||||||
|
IRVar2RISCVReg(icmp_act->operand1_full, sz, "t0", layout, code_lines);
|
||||||
|
IRVar2RISCVReg(icmp_act->operand2_full, sz, "t1", layout, code_lines);
|
||||||
|
if (icmp_act->op == "eq") {
|
||||||
|
code_lines.push_back("xor t2, t0, t1");
|
||||||
|
code_lines.push_back("seqz t2, t2");
|
||||||
|
} else if (icmp_act->op == "ne") {
|
||||||
|
code_lines.push_back("xor t2, t0, t1");
|
||||||
|
code_lines.push_back("snez t2, t2");
|
||||||
|
} else if (icmp_act->op == "slt") {
|
||||||
|
code_lines.push_back("slt t2, t0, t1");
|
||||||
|
} else if (icmp_act->op == "sle") {
|
||||||
|
code_lines.push_back("slt t2, t1, t0");
|
||||||
|
code_lines.push_back("xori t2, t2, 1");
|
||||||
|
} else if (icmp_act->op == "sgt") {
|
||||||
|
code_lines.push_back("slt t2, t1, t0");
|
||||||
|
} else if (icmp_act->op == "sge") {
|
||||||
|
code_lines.push_back("slt t2, t0, t1");
|
||||||
|
code_lines.push_back("xori t2, t2, 1");
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown icmp operation");
|
||||||
|
}
|
||||||
|
GenerateWriteAccess(icmp_act->result_full, 1, "t2", layout, code_lines);
|
||||||
|
} else if (auto call_act = std::dynamic_pointer_cast<CallItem>(act)) {
|
||||||
|
size_t num_of_args = call_act->args_ty.size();
|
||||||
|
if (call_act->args_ty.size() != call_act->args_val_full.size()) {
|
||||||
|
throw std::runtime_error("args_ty and args_full_name should have the same size");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < num_of_args && i < 8; i++) {
|
||||||
|
IRVar2RISCVReg(call_act->args_val_full[i], CalcSize(call_act->args_ty[i]), "a" + std::to_string(i), layout,
|
||||||
|
code_lines);
|
||||||
|
}
|
||||||
|
if (num_of_args >= 8) {
|
||||||
|
size_t ps_delta = (num_of_args * 4 + 15) / 16 * 16;
|
||||||
|
code_lines.push_back("addi sp, sp, -" + std::to_string(ps_delta));
|
||||||
|
for (size_t i = 8; i < num_of_args; i++) {
|
||||||
|
IRVar2RISCVReg(call_act->args_val_full[i], CalcSize(call_act->args_ty[i]), "t0", layout, code_lines);
|
||||||
|
code_lines.push_back("sw t0, " + std::to_string((i - 8) * 4) + "(sp)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code_lines.push_back("call " + call_act->func_name_raw);
|
||||||
|
if (call_act->result_full != "") {
|
||||||
|
size_t ret_sz = CalcSize(call_act->return_type);
|
||||||
|
GenerateWriteAccess(call_act->result_full, ret_sz, "a0", layout, code_lines);
|
||||||
|
}
|
||||||
|
} else if (auto phi_act = std::dynamic_pointer_cast<PhiItem>(act)) {
|
||||||
|
if (!process_phi) {
|
||||||
|
return; // for efficiency, phi actions are implemented as store action in the previous block
|
||||||
|
}
|
||||||
|
// TODO: implement this
|
||||||
|
// throw std::runtime_error("not implemented");
|
||||||
|
} else if (auto select_act = std::dynamic_pointer_cast<SelectItem>(act)) {
|
||||||
|
// TODO: implement this
|
||||||
|
// throw std::runtime_error("not implemented");
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown action type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace NaiveBackend
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cctype>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -93,8 +94,12 @@ class FuncLayout {
|
|||||||
friend void ::GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
friend void ::GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
friend void GenerateReadAccess(std::string val, size_t bytes, std::string output_reg, FuncLayout &layout,
|
friend void GenerateReadAccess(std::string val, size_t bytes, std::string output_reg, FuncLayout &layout,
|
||||||
std::vector<std::string> &code_lines);
|
std::vector<std::string> &code_lines);
|
||||||
friend inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
friend void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
||||||
std::vector<std::string> &code_lines);
|
std::vector<std::string> &code_lines);
|
||||||
|
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
||||||
|
FuncLayout &layout,
|
||||||
|
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
||||||
|
bool process_phi);
|
||||||
std::unordered_map<std::string, size_t> local_items;
|
std::unordered_map<std::string, size_t> local_items;
|
||||||
std::unordered_map<std::string, size_t> arg_offset;
|
std::unordered_map<std::string, size_t> arg_offset;
|
||||||
size_t cur_pos;
|
size_t cur_pos;
|
||||||
@ -127,7 +132,8 @@ inline void GenerateReadAccess(std::string val, size_t bytes, std::string output
|
|||||||
}
|
}
|
||||||
size_t offset = layout.arg_offset.at(val);
|
size_t offset = layout.arg_offset.at(val);
|
||||||
if (offset < 8) {
|
if (offset < 8) {
|
||||||
output_reg = "a" + std::to_string(offset);
|
std::string src_reg = "a" + std::to_string(offset);
|
||||||
|
code_lines.push_back("mv " + output_reg + ", " + src_reg);
|
||||||
} else {
|
} else {
|
||||||
size_t spilled_offset = (offset - 8) * 4; // just*4, which is different from the real riscv
|
size_t spilled_offset = (offset - 8) * 4; // just*4, which is different from the real riscv
|
||||||
std::string cmd;
|
std::string cmd;
|
||||||
@ -137,7 +143,7 @@ inline void GenerateReadAccess(std::string val, size_t bytes, std::string output
|
|||||||
cmd = "lw";
|
cmd = "lw";
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Unknown bytes");
|
throw std::runtime_error("Unknown bytes");
|
||||||
cmd += " " + output_reg + ", " + std::to_string(spilled_offset) + "(fp)";
|
cmd += " " + output_reg + ", " + std::to_string(spilled_offset) + "(s0)";
|
||||||
code_lines.push_back(cmd);
|
code_lines.push_back(cmd);
|
||||||
}
|
}
|
||||||
} else if (val.size() > 13 && val.substr(0, 13) == "@.var.global.") {
|
} else if (val.size() > 13 && val.substr(0, 13) == "@.var.global.") {
|
||||||
@ -147,22 +153,49 @@ inline void GenerateReadAccess(std::string val, size_t bytes, std::string output
|
|||||||
} else if (val.size() > 12 && val.substr(0, 12) == "%.var.local.") {
|
} else if (val.size() > 12 && val.substr(0, 12) == "%.var.local.") {
|
||||||
// local variable address keeper
|
// local variable address keeper
|
||||||
size_t offset = layout.QueryOffeset(val);
|
size_t offset = layout.QueryOffeset(val);
|
||||||
code_lines.push_back("addi " + output_reg + ", fp, -" + std::to_string(offset));
|
code_lines.push_back("addi " + output_reg + ", s0, -" + std::to_string(offset));
|
||||||
} else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") {
|
} else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") {
|
||||||
// tmp variable, not address keeper
|
// tmp variable, not address keeper
|
||||||
size_t offset = layout.QueryOffeset(val);
|
size_t offset = layout.QueryOffeset(val);
|
||||||
code_lines.push_back("addi " + output_reg + ", fp, -" + std::to_string(offset));
|
|
||||||
if (bytes == 1) {
|
if (bytes == 1) {
|
||||||
code_lines.push_back("lb " + output_reg + ", 0(" + output_reg + ")");
|
code_lines.push_back("lb " + output_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||||
} else if (bytes == 4) {
|
} else if (bytes == 4) {
|
||||||
code_lines.push_back("lw " + output_reg + ", 0(" + output_reg + ")");
|
code_lines.push_back("lw " + output_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Unknown bytes");
|
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);
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Unknown variable type with name=" + val);
|
throw std::runtime_error("Unknown variable type with name=" + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline void StoreImmToReg(int imm, std::string reg, std::vector<std::string> &code_lines) {
|
||||||
|
// if (imm >= 2048) {
|
||||||
|
// code_lines.push_back("lui " + reg + ", " + std::to_string(imm >> 12));
|
||||||
|
// code_lines.push_back("ori " + reg + ", " + reg + ", " + std::to_string(imm & 0x7ff));
|
||||||
|
// } else {
|
||||||
|
// code_lines.push_back("ori " + reg + ", x0, " + std::to_string(imm));
|
||||||
|
// }
|
||||||
|
code_lines.push_back("li " + reg + ", " + std::to_string(imm));
|
||||||
|
}
|
||||||
|
inline void IRVar2RISCVReg(std::string val, size_t bytes, std::string output_reg, FuncLayout &layout,
|
||||||
|
std::vector<std::string> &code_lines) {
|
||||||
|
if (val[0] == '-') {
|
||||||
|
if (val == "-1") {
|
||||||
|
StoreImmToReg(-1, output_reg, code_lines);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Negative imm in IR is not supported");
|
||||||
|
}
|
||||||
|
if (val == "null") {
|
||||||
|
StoreImmToReg(0, output_reg, code_lines);
|
||||||
|
} else if (std::isdigit(val[0])) {
|
||||||
|
StoreImmToReg(std::stoull(val), output_reg, code_lines);
|
||||||
|
} else {
|
||||||
|
GenerateReadAccess(val, bytes, output_reg, layout, code_lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
||||||
std::vector<std::string> &code_lines) {
|
std::vector<std::string> &code_lines) {
|
||||||
if (val.size() > 4 && val.substr(val.size() - 4, 4) == ".val") {
|
if (val.size() > 4 && val.substr(val.size() - 4, 4) == ".val") {
|
||||||
@ -177,11 +210,10 @@ inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_
|
|||||||
} else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") {
|
} else if (val.size() > 10 && val.substr(0, 10) == "%.var.tmp.") {
|
||||||
// tmp variable, not address keeper
|
// tmp variable, not address keeper
|
||||||
size_t offset = layout.QueryOffeset(val);
|
size_t offset = layout.QueryOffeset(val);
|
||||||
code_lines.push_back("addi " + data_reg + ", fp, -" + std::to_string(offset));
|
|
||||||
if (bytes == 1) {
|
if (bytes == 1) {
|
||||||
code_lines.push_back("sb " + data_reg + ", 0(" + data_reg + ")");
|
code_lines.push_back("sb " + data_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||||
} else if (bytes == 4) {
|
} else if (bytes == 4) {
|
||||||
code_lines.push_back("sw " + data_reg + ", 0(" + data_reg + ")");
|
code_lines.push_back("sw " + data_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Unknown bytes");
|
throw std::runtime_error("Unknown bytes");
|
||||||
}
|
}
|
||||||
@ -189,6 +221,20 @@ inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_
|
|||||||
throw std::runtime_error("Unknown variable type with name=" + val);
|
throw std::runtime_error("Unknown variable type with name=" + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline size_t CalcSize(const LLVMType &tp) {
|
||||||
|
if (std::holds_alternative<LLVMIRIntType>(tp)) {
|
||||||
|
auto &int_tp = std::get<LLVMIRIntType>(tp);
|
||||||
|
return (int_tp.bits + 7) / 8;
|
||||||
|
} else if (std::holds_alternative<LLVMIRPTRType>(tp)) {
|
||||||
|
return 4;
|
||||||
|
} else if (std::holds_alternative<LLVMVOIDType>(tp)) {
|
||||||
|
throw std::runtime_error("Cannot calculate size of void type");
|
||||||
|
return 0;
|
||||||
|
} else if (std::holds_alternative<LLVMIRCLASSTYPE>(tp)) {
|
||||||
|
throw std::runtime_error("Cannot calculate size of class type");
|
||||||
|
} else
|
||||||
|
throw std::runtime_error("Unknown type");
|
||||||
|
}
|
||||||
} // namespace NaiveBackend
|
} // namespace NaiveBackend
|
||||||
|
|
||||||
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
@ -359,8 +359,24 @@ void IRBuilder::ActuralVisit(JmpStatement_ASTNode *node) {
|
|||||||
// return
|
// return
|
||||||
if (node->return_value) {
|
if (node->return_value) {
|
||||||
node->return_value->accept(this);
|
node->return_value->accept(this);
|
||||||
|
std::string res = node->return_value->IR_result_full;
|
||||||
|
if (res[0] == '#') {
|
||||||
|
res = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = res;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = node->return_value->IR_result_full.substr(1);
|
||||||
|
} else if (res[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[res.substr(1)];
|
||||||
|
res = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
cur_block->exit_action = std::make_shared<RETAction>();
|
cur_block->exit_action = std::make_shared<RETAction>();
|
||||||
std::dynamic_pointer_cast<RETAction>(cur_block->exit_action)->value = node->return_value->IR_result_full;
|
std::dynamic_pointer_cast<RETAction>(cur_block->exit_action)->value = res;
|
||||||
} else {
|
} else {
|
||||||
cur_block->exit_action = std::make_shared<RETAction>();
|
cur_block->exit_action = std::make_shared<RETAction>();
|
||||||
}
|
}
|
||||||
@ -534,9 +550,25 @@ void IRBuilder::ActuralVisit(NewExpr_ASTNode *node) {
|
|||||||
void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) {
|
void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) {
|
||||||
if (!node->is_function) {
|
if (!node->is_function) {
|
||||||
node->base->accept(this);
|
node->base->accept(this);
|
||||||
|
std::string base_res = node->base->IR_result_full;
|
||||||
|
if (base_res[0] == '#') {
|
||||||
|
base_res = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = base_res;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = node->base->IR_result_full.substr(1);
|
||||||
|
} else if (base_res[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[base_res.substr(1)];
|
||||||
|
base_res = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
|
std::string type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
|
||||||
IRClassInfo class_info = global_scope->fetch_class_info(type_of_base);
|
IRClassInfo class_info = global_scope->fetch_class_info(type_of_base);
|
||||||
std::string base_ptr = node->base->IR_result_full;
|
std::string base_ptr = base_res;
|
||||||
size_t idx = class_info.member_var_offset[node->member];
|
size_t idx = class_info.member_var_offset[node->member];
|
||||||
auto member_addr_cal = std::make_shared<GetElementPtrAction>();
|
auto member_addr_cal = std::make_shared<GetElementPtrAction>();
|
||||||
cur_block->actions.push_back(member_addr_cal);
|
cur_block->actions.push_back(member_addr_cal);
|
||||||
@ -557,16 +589,48 @@ void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node->base->accept(this);
|
node->base->accept(this);
|
||||||
|
std::string base_res = node->base->IR_result_full;
|
||||||
|
if (base_res[0] == '#') {
|
||||||
|
base_res = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = base_res;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = node->base->IR_result_full.substr(1);
|
||||||
|
} else if (base_res[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[base_res.substr(1)];
|
||||||
|
base_res = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string type_of_base;
|
std::string type_of_base;
|
||||||
if (std::holds_alternative<IdentifierType>(node->base->expr_type_info))
|
if (std::holds_alternative<IdentifierType>(node->base->expr_type_info))
|
||||||
type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
|
type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
|
||||||
std::string base_ptr = node->base->IR_result_full;
|
std::string base_ptr = base_res;
|
||||||
std::string func_name = type_of_base + "." + node->member;
|
std::string func_name = type_of_base + "." + node->member;
|
||||||
if (std::holds_alternative<ArrayType>(node->base->expr_type_info)) func_name = ".builtin.GetArrayLength";
|
if (std::holds_alternative<ArrayType>(node->base->expr_type_info)) func_name = ".builtin.GetArrayLength";
|
||||||
std::vector<std::string> arg_val;
|
std::vector<std::string> arg_val;
|
||||||
for (size_t i = 0; i < node->arguments.size(); i++) {
|
for (size_t i = 0; i < node->arguments.size(); i++) {
|
||||||
node->arguments[i]->accept(this);
|
node->arguments[i]->accept(this);
|
||||||
arg_val.push_back(node->arguments[i]->IR_result_full);
|
std::string arg_value = node->arguments[i]->IR_result_full;
|
||||||
|
if (arg_value[0] == '#') {
|
||||||
|
arg_value = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = arg_value;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = node->arguments[i]->IR_result_full.substr(1);
|
||||||
|
} else if (arg_value[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[arg_value.substr(1)];
|
||||||
|
arg_value = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_val.push_back(arg_value);
|
||||||
}
|
}
|
||||||
auto call_act = std::make_shared<CallItem>();
|
auto call_act = std::make_shared<CallItem>();
|
||||||
cur_block->actions.push_back(call_act);
|
cur_block->actions.push_back(call_act);
|
||||||
@ -1167,7 +1231,23 @@ void IRBuilder::ActuralVisit(FunctionCallExpr_ASTNode *node) {
|
|||||||
call->args_ty.push_back(LLVMIRPTRType());
|
call->args_ty.push_back(LLVMIRPTRType());
|
||||||
for (auto &arg : node->arguments) {
|
for (auto &arg : node->arguments) {
|
||||||
arg->accept(this);
|
arg->accept(this);
|
||||||
call->args_val_full.push_back(arg->IR_result_full);
|
std::string arg_value = arg->IR_result_full;
|
||||||
|
if (arg_value[0] == '#') {
|
||||||
|
arg_value = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = arg_value;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = arg->IR_result_full.substr(1);
|
||||||
|
} else if (arg_value[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[arg_value.substr(1)];
|
||||||
|
arg_value = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call->args_val_full.push_back(arg_value);
|
||||||
call->args_ty.push_back(Type_AST2LLVM(arg->expr_type_info));
|
call->args_ty.push_back(Type_AST2LLVM(arg->expr_type_info));
|
||||||
}
|
}
|
||||||
cur_block->actions.push_back(call);
|
cur_block->actions.push_back(call);
|
||||||
@ -1181,7 +1261,23 @@ void IRBuilder::ActuralVisit(FunctionCallExpr_ASTNode *node) {
|
|||||||
call->func_name_raw = node->func_name;
|
call->func_name_raw = node->func_name;
|
||||||
for (auto &arg : node->arguments) {
|
for (auto &arg : node->arguments) {
|
||||||
arg->accept(this);
|
arg->accept(this);
|
||||||
call->args_val_full.push_back(arg->IR_result_full);
|
std::string arg_value = arg->IR_result_full;
|
||||||
|
if (arg_value[0] == '#') {
|
||||||
|
arg_value = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
|
auto const_array_construct_call = std::make_shared<CallItem>();
|
||||||
|
cur_block->actions.push_back(const_array_construct_call);
|
||||||
|
const_array_construct_call->result_full = arg_value;
|
||||||
|
const_array_construct_call->return_type = LLVMIRPTRType();
|
||||||
|
const_array_construct_call->func_name_raw = arg->IR_result_full.substr(1);
|
||||||
|
} else if (arg_value[0] == '!') {
|
||||||
|
// inline builder
|
||||||
|
auto inline_builder = inline_builders[arg_value.substr(1)];
|
||||||
|
arg_value = std::dynamic_pointer_cast<RETAction>(inline_builder->exit_action)->value;
|
||||||
|
for (auto &act : inline_builder->actions) {
|
||||||
|
cur_block->actions.push_back(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call->args_val_full.push_back(arg_value);
|
||||||
call->args_ty.push_back(Type_AST2LLVM(arg->expr_type_info));
|
call->args_ty.push_back(Type_AST2LLVM(arg->expr_type_info));
|
||||||
}
|
}
|
||||||
cur_block->actions.push_back(call);
|
cur_block->actions.push_back(call);
|
||||||
|
@ -28,6 +28,7 @@ int main(int argc, char **argv) {
|
|||||||
try {
|
try {
|
||||||
SemanticCheck(fin, ast);
|
SemanticCheck(fin, ast);
|
||||||
auto IR = BuildIR(ast);
|
auto IR = BuildIR(ast);
|
||||||
|
// IR->RecursivePrint(fout); return 0;
|
||||||
IR->RecursivePrint(std::cerr);
|
IR->RecursivePrint(std::cerr);
|
||||||
GenerateNaiveASM(fout, IR);
|
GenerateNaiveASM(fout, IR);
|
||||||
} catch (const SemanticError &err) {
|
} catch (const SemanticError &err) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "IR/IR_basic.h"
|
#include "IR/IR_basic.h"
|
||||||
#include "build_layout.hpp"
|
#include "build_layout.hpp"
|
||||||
|
#include "codegen.hpp"
|
||||||
using namespace NaiveBackend;
|
using namespace NaiveBackend;
|
||||||
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog) {
|
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog) {
|
||||||
auto riscv = std::make_shared<RISCVProgItem>();
|
auto riscv = std::make_shared<RISCVProgItem>();
|
||||||
@ -21,12 +22,12 @@ void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog) {
|
|||||||
for (auto func_def : prog->function_defs) {
|
for (auto func_def : prog->function_defs) {
|
||||||
if (func_def->init_block) {
|
if (func_def->init_block) {
|
||||||
for (auto act : func_def->init_block->actions) {
|
for (auto act : func_def->init_block->actions) {
|
||||||
ScanForVar(func_layouts[func_def->func_name_raw], act);
|
ScanForVar(func_layouts[func_def->func_name_raw], act, prog->low_level_class_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto block : func_def->basic_blocks) {
|
for (auto block : func_def->basic_blocks) {
|
||||||
for (auto act : block->actions) {
|
for (auto act : block->actions) {
|
||||||
ScanForVar(func_layouts[func_def->func_name_raw], act);
|
ScanForVar(func_layouts[func_def->func_name_raw], act, prog->low_level_class_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FuncLayout &layout = func_layouts[func_def->func_name_raw];
|
FuncLayout &layout = func_layouts[func_def->func_name_raw];
|
||||||
@ -47,11 +48,36 @@ void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog) {
|
|||||||
auto func_asm = std::make_shared<RISCVFuncItem>();
|
auto func_asm = std::make_shared<RISCVFuncItem>();
|
||||||
riscv->funcs.push_back(func_asm);
|
riscv->funcs.push_back(func_asm);
|
||||||
func_asm->full_label = func_def->func_name_raw;
|
func_asm->full_label = func_def->func_name_raw;
|
||||||
|
FuncLayout &layout = func_layouts[func_def->func_name_raw];
|
||||||
|
func_asm->code_lines.push_back("addi sp, sp, -" + std::to_string(layout.total_frame_size));
|
||||||
|
func_asm->code_lines.push_back("sw ra, " + std::to_string(layout.total_frame_size - 4) + "(sp)");
|
||||||
|
func_asm->code_lines.push_back("sw s0, " + std::to_string(layout.total_frame_size - 8) + "(sp)");
|
||||||
|
func_asm->code_lines.push_back("addi s0, sp, " + std::to_string(layout.total_frame_size));
|
||||||
if (func_def->init_block) {
|
if (func_def->init_block) {
|
||||||
func_asm->code_lines.push_back(".entrylabel." + func_def->init_block->label_full + ":");
|
func_asm->code_lines.push_back(".entrylabel." + func_def->init_block->label_full + ":");
|
||||||
|
for (auto act : func_def->init_block->actions) {
|
||||||
|
NaiveBackend::GenerateASM(act, func_asm->code_lines, func_layouts[func_def->func_name_raw],
|
||||||
|
prog->low_level_class_info);
|
||||||
|
}
|
||||||
|
if (func_def->init_block->exit_action->corresponding_phi) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
NaiveBackend::GenerateASM(func_def->init_block->exit_action, func_asm->code_lines,
|
||||||
|
func_layouts[func_def->func_name_raw], prog->low_level_class_info);
|
||||||
}
|
}
|
||||||
for (auto block : func_def->basic_blocks) {
|
for (auto block : func_def->basic_blocks) {
|
||||||
func_asm->code_lines.push_back(".entrylabel." + block->label_full + ":");
|
func_asm->code_lines.push_back(".entrylabel." + block->label_full + ":");
|
||||||
|
for (auto act : block->actions) {
|
||||||
|
NaiveBackend::GenerateASM(act, func_asm->code_lines, func_layouts[func_def->func_name_raw],
|
||||||
|
prog->low_level_class_info);
|
||||||
|
}
|
||||||
|
if (block->exit_action->corresponding_phi) {
|
||||||
|
NaiveBackend::GenerateASM(block->exit_action->corresponding_phi, func_asm->code_lines,
|
||||||
|
func_layouts[func_def->func_name_raw], prog->low_level_class_info, true);
|
||||||
|
}
|
||||||
|
NaiveBackend::GenerateASM(block->exit_action, func_asm->code_lines, func_layouts[func_def->func_name_raw],
|
||||||
|
prog->low_level_class_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user