basically write codegen
This commit is contained in:
@ -71,9 +71,18 @@ class JMPActionItem : public ActionItem {
|
||||
public:
|
||||
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 {
|
||||
friend class IRBuilder;
|
||||
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 true_label_full;
|
||||
std::string false_label_full;
|
||||
@ -88,6 +97,10 @@ class UNConditionJMPAction : public JMPActionItem {
|
||||
friend class IRBuilder;
|
||||
friend class FunctionDefItem;
|
||||
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;
|
||||
|
||||
public:
|
||||
@ -98,6 +111,10 @@ class RETAction : public JMPActionItem {
|
||||
friend class IRBuilder;
|
||||
friend class FunctionDefItem;
|
||||
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;
|
||||
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 {
|
||||
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 operand1_full;
|
||||
std::string operand2_full;
|
||||
@ -145,7 +164,7 @@ class BinaryOperationAction : public ActionItem {
|
||||
};
|
||||
class AllocaAction : public ActionItem {
|
||||
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;
|
||||
LLVMType type;
|
||||
size_t num;
|
||||
@ -169,7 +188,11 @@ class AllocaAction : public ActionItem {
|
||||
};
|
||||
class LoadAction : public ActionItem {
|
||||
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;
|
||||
LLVMType ty;
|
||||
std::string ptr_full;
|
||||
@ -190,7 +213,11 @@ class LoadAction : public ActionItem {
|
||||
};
|
||||
class StoreAction : public ActionItem {
|
||||
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;
|
||||
std::string value_full;
|
||||
std::string ptr_full;
|
||||
@ -211,7 +238,7 @@ class StoreAction : public ActionItem {
|
||||
};
|
||||
class GetElementPtrAction : public ActionItem {
|
||||
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;
|
||||
LLVMType ty;
|
||||
std::string ptr_full;
|
||||
@ -239,7 +266,11 @@ class GetElementPtrAction : public ActionItem {
|
||||
};
|
||||
class ICMPAction : public ActionItem {
|
||||
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 operand1_full;
|
||||
std::string operand2_full;
|
||||
@ -264,7 +295,7 @@ class BlockItem : public LLVMIRItemBase {
|
||||
friend class IRBuilder;
|
||||
friend class FunctionDefItem;
|
||||
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::vector<std::shared_ptr<ActionItem>> actions;
|
||||
std::shared_ptr<JMPActionItem> exit_action;
|
||||
@ -281,7 +312,11 @@ class BlockItem : public LLVMIRItemBase {
|
||||
};
|
||||
class CallItem : public ActionItem {
|
||||
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;
|
||||
LLVMType return_type;
|
||||
std::string func_name_raw;
|
||||
@ -330,7 +365,7 @@ class CallItem : public ActionItem {
|
||||
|
||||
class PhiItem : public ActionItem {
|
||||
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;
|
||||
LLVMType ty;
|
||||
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 {
|
||||
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 cond_full;
|
||||
std::string true_val_full;
|
||||
|
@ -6,21 +6,8 @@
|
||||
#include "tools.h"
|
||||
|
||||
namespace NaiveBackend {
|
||||
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");
|
||||
}
|
||||
inline void ScanForVar(FuncLayout &layout, std::shared_ptr<ActionItem> action) {
|
||||
inline void ScanForVar(FuncLayout &layout, std::shared_ptr<ActionItem> action,
|
||||
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info) {
|
||||
if (std::dynamic_pointer_cast<JMPActionItem>(action)) {
|
||||
throw std::runtime_error("JMPActionItem should not be in the layout");
|
||||
} 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 == "") {
|
||||
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)) {
|
||||
if (icmp_act->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
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
@ -93,8 +94,12 @@ class FuncLayout {
|
||||
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,
|
||||
std::vector<std::string> &code_lines);
|
||||
friend inline void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
||||
std::vector<std::string> &code_lines);
|
||||
friend void GenerateWriteAccess(std::string val, size_t bytes, std::string data_reg, FuncLayout &layout,
|
||||
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> arg_offset;
|
||||
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);
|
||||
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 {
|
||||
size_t spilled_offset = (offset - 8) * 4; // just*4, which is different from the real riscv
|
||||
std::string cmd;
|
||||
@ -137,7 +143,7 @@ inline void GenerateReadAccess(std::string val, size_t bytes, std::string output
|
||||
cmd = "lw";
|
||||
else
|
||||
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);
|
||||
}
|
||||
} 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.") {
|
||||
// local variable address keeper
|
||||
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.") {
|
||||
// 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 + ")");
|
||||
code_lines.push_back("lb " + output_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||
} 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 {
|
||||
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 {
|
||||
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,
|
||||
std::vector<std::string> &code_lines) {
|
||||
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.") {
|
||||
// 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 + ")");
|
||||
code_lines.push_back("sb " + data_reg + ", -" + std::to_string(offset) + "(s0)");
|
||||
} 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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
Reference in New Issue
Block a user