In half way of write codegen
This commit is contained in:
@ -48,6 +48,7 @@ class TypeDefItem : public LLVMIRItemBase {
|
|||||||
};
|
};
|
||||||
class GlobalVarDefItem : public LLVMIRItemBase {
|
class GlobalVarDefItem : public LLVMIRItemBase {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
LLVMType type;
|
LLVMType type;
|
||||||
std::string name_raw;
|
std::string name_raw;
|
||||||
|
|
||||||
@ -66,9 +67,13 @@ class GlobalVarDefItem : public LLVMIRItemBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
class ActionItem : public LLVMIRItemBase {};
|
class ActionItem : public LLVMIRItemBase {};
|
||||||
class JMPActionItem : public ActionItem {};
|
class JMPActionItem : public ActionItem {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<class PhiItem> corresponding_phi;
|
||||||
|
};
|
||||||
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);
|
||||||
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;
|
||||||
@ -82,6 +87,7 @@ class BRAction : public JMPActionItem {
|
|||||||
class UNConditionJMPAction : public JMPActionItem {
|
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);
|
||||||
std::string label_full;
|
std::string label_full;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -91,6 +97,7 @@ class UNConditionJMPAction : public JMPActionItem {
|
|||||||
class RETAction : public JMPActionItem {
|
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);
|
||||||
LLVMType type;
|
LLVMType type;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
@ -108,8 +115,12 @@ 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);
|
||||||
std::string op;
|
std::string op;
|
||||||
std::string operand1_full;
|
std::string operand1_full;
|
||||||
std::string operand2_full;
|
std::string operand2_full;
|
||||||
@ -134,6 +145,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);
|
||||||
std::string name_full;
|
std::string name_full;
|
||||||
LLVMType type;
|
LLVMType type;
|
||||||
size_t num;
|
size_t num;
|
||||||
@ -157,6 +169,7 @@ 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);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -177,6 +190,7 @@ 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);
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string value_full;
|
std::string value_full;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -197,6 +211,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);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType ty;
|
LLVMType ty;
|
||||||
std::string ptr_full;
|
std::string ptr_full;
|
||||||
@ -224,6 +239,7 @@ 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);
|
||||||
std::string op;
|
std::string op;
|
||||||
std::string operand1_full;
|
std::string operand1_full;
|
||||||
std::string operand2_full;
|
std::string operand2_full;
|
||||||
@ -247,6 +263,8 @@ class ICMPAction : public ActionItem {
|
|||||||
class BlockItem : public LLVMIRItemBase {
|
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 NaiveBackend::ScanForVar(class NaiveBackend::FuncLayout &layout, std::shared_ptr<ActionItem> action);
|
||||||
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;
|
||||||
@ -263,6 +281,7 @@ 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);
|
||||||
std::string result_full;
|
std::string result_full;
|
||||||
LLVMType return_type;
|
LLVMType return_type;
|
||||||
std::string func_name_raw;
|
std::string func_name_raw;
|
||||||
@ -311,6 +330,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);
|
||||||
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)
|
||||||
@ -337,6 +357,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);
|
||||||
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;
|
||||||
@ -367,6 +388,7 @@ class SelectItem : public ActionItem {
|
|||||||
};
|
};
|
||||||
class FunctionDefItem : public LLVMIRItemBase {
|
class FunctionDefItem : public LLVMIRItemBase {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
LLVMType return_type;
|
LLVMType return_type;
|
||||||
std::string func_name_raw;
|
std::string func_name_raw;
|
||||||
std::vector<LLVMType> args;
|
std::vector<LLVMType> args;
|
||||||
@ -451,6 +473,7 @@ class FunctionDeclareItem : public LLVMIRItemBase {
|
|||||||
};
|
};
|
||||||
class ConstStrItem : public LLVMIRItemBase {
|
class ConstStrItem : public LLVMIRItemBase {
|
||||||
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
|
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
|
||||||
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
std::string string_raw;
|
std::string string_raw;
|
||||||
size_t const_str_id;
|
size_t const_str_id;
|
||||||
@ -484,11 +507,13 @@ class ConstStrItem : public LLVMIRItemBase {
|
|||||||
class ModuleItem : public LLVMIRItemBase {
|
class ModuleItem : public LLVMIRItemBase {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
|
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
|
||||||
|
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
std::vector<std::shared_ptr<ConstStrItem>> const_strs;
|
std::vector<std::shared_ptr<ConstStrItem>> const_strs;
|
||||||
std::vector<std::shared_ptr<FunctionDeclareItem>> function_declares;
|
std::vector<std::shared_ptr<FunctionDeclareItem>> function_declares;
|
||||||
std::vector<std::shared_ptr<TypeDefItem>> type_defs;
|
std::vector<std::shared_ptr<TypeDefItem>> type_defs;
|
||||||
std::vector<std::shared_ptr<GlobalVarDefItem>> global_var_defs;
|
std::vector<std::shared_ptr<GlobalVarDefItem>> global_var_defs;
|
||||||
std::vector<std::shared_ptr<FunctionDefItem>> function_defs;
|
std::vector<std::shared_ptr<FunctionDefItem>> function_defs;
|
||||||
|
std::unordered_map<std::string, IRClassInfo> low_level_class_info;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ModuleItem() = default;
|
ModuleItem() = default;
|
||||||
|
75
include/naivebackend/build_layout.hpp
Normal file
75
include/naivebackend/build_layout.hpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "IR/IR_basic.h"
|
||||||
|
#include "naivebackend.h"
|
||||||
|
#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) {
|
||||||
|
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)) {
|
||||||
|
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<AllocaAction>(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<LoadAction>(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<StoreAction>(action)) {
|
||||||
|
// just do nothing
|
||||||
|
} else if (auto get_element_act = std::dynamic_pointer_cast<GetElementPtrAction>(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<ICMPAction>(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<CallItem>(action)) {
|
||||||
|
if (call_act->result_full == "") {
|
||||||
|
if (!std::holds_alternative<LLVMVOIDType>(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<PhiItem>(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<SelectItem>(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
|
@ -1,8 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
#include "IR/IR_basic.h"
|
#include "IR/IR_basic.h"
|
||||||
class RISCVAsmItemBase {
|
class RISCVAsmItemBase {
|
||||||
public:
|
public:
|
||||||
@ -13,27 +17,178 @@ class RISCVAsmItemBase {
|
|||||||
namespace NaiveBackend {
|
namespace NaiveBackend {
|
||||||
class RISCVConstStrItem : public RISCVAsmItemBase {
|
class RISCVConstStrItem : public RISCVAsmItemBase {
|
||||||
public:
|
public:
|
||||||
|
std::string full_label;
|
||||||
|
std::string content;
|
||||||
RISCVConstStrItem() = default;
|
RISCVConstStrItem() = default;
|
||||||
~RISCVConstStrItem() = default;
|
~RISCVConstStrItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const override;
|
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 {
|
class RISCVGlobalVarItem : public RISCVAsmItemBase {
|
||||||
public:
|
public:
|
||||||
|
std::string full_label;
|
||||||
RISCVGlobalVarItem() = default;
|
RISCVGlobalVarItem() = default;
|
||||||
~RISCVGlobalVarItem() = default;
|
~RISCVGlobalVarItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const override;
|
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 {
|
class RISCVFuncItem : public RISCVAsmItemBase {
|
||||||
|
friend void ::GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::string full_label;
|
||||||
|
std::vector<std::string> code_lines;
|
||||||
RISCVFuncItem() = default;
|
RISCVFuncItem() = default;
|
||||||
~RISCVFuncItem() = default;
|
~RISCVFuncItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const override;
|
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 {
|
class RISCVProgItem : public RISCVAsmItemBase {
|
||||||
public:
|
public:
|
||||||
|
std::vector<std::shared_ptr<RISCVConstStrItem>> const_strs;
|
||||||
|
std::vector<std::shared_ptr<RISCVGlobalVarItem>> global_vars;
|
||||||
|
std::vector<std::shared_ptr<RISCVFuncItem>> funcs;
|
||||||
RISCVProgItem() = default;
|
RISCVProgItem() = default;
|
||||||
~RISCVProgItem() = default;
|
~RISCVProgItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const override;
|
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<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);
|
||||||
|
std::unordered_map<std::string, size_t> local_items;
|
||||||
|
std::unordered_map<std::string, size_t> 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<std::string> &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<std::string> &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<ModuleItem> prog);
|
void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
@ -92,6 +92,7 @@ void IRBuilder::ActuralVisit(FuncDef_ASTNode *node) {
|
|||||||
void IRBuilder::ActuralVisit(ClassDef_ASTNode *node) {
|
void IRBuilder::ActuralVisit(ClassDef_ASTNode *node) {
|
||||||
is_in_class_def = true;
|
is_in_class_def = true;
|
||||||
cur_class_name = node->class_name;
|
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<TypeDefItem>();
|
auto tpdf = std::make_shared<TypeDefItem>();
|
||||||
tpdf->class_name_raw = node->class_name;
|
tpdf->class_name_raw = node->class_name;
|
||||||
cur_class = tpdf;
|
cur_class = tpdf;
|
||||||
@ -950,6 +951,8 @@ void IRBuilder::ActuralVisit(LAndExpr_ASTNode *node) {
|
|||||||
size_t new_block_id = block_counter++;
|
size_t new_block_id = block_counter++;
|
||||||
auto right_cal_block = std::make_shared<BlockItem>();
|
auto right_cal_block = std::make_shared<BlockItem>();
|
||||||
auto new_block = std::make_shared<BlockItem>();
|
auto new_block = std::make_shared<BlockItem>();
|
||||||
|
auto phi_act = std::make_shared<PhiItem>();
|
||||||
|
|
||||||
right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id);
|
right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id);
|
||||||
new_block->label_full = "label_" + std::to_string(new_block_id);
|
new_block->label_full = "label_" + std::to_string(new_block_id);
|
||||||
cur_block->exit_action = std::make_shared<BRAction>();
|
cur_block->exit_action = std::make_shared<BRAction>();
|
||||||
@ -957,15 +960,18 @@ void IRBuilder::ActuralVisit(LAndExpr_ASTNode *node) {
|
|||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->true_label_full = right_cal_block->label_full;
|
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->true_label_full = right_cal_block->label_full;
|
||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->false_label_full = new_block->label_full;
|
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->false_label_full = new_block->label_full;
|
||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->cond = node->left->IR_result_full;
|
std::dynamic_pointer_cast<BRAction>(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_func->basic_blocks.push_back(right_cal_block);
|
||||||
cur_block = right_cal_block;
|
cur_block = right_cal_block;
|
||||||
node->right->accept(this);
|
node->right->accept(this);
|
||||||
cur_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
cur_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
||||||
auto right_block_end = cur_block;
|
auto right_block_end = cur_block;
|
||||||
std::dynamic_pointer_cast<UNConditionJMPAction>(cur_block->exit_action)->label_full = new_block->label_full;
|
std::dynamic_pointer_cast<UNConditionJMPAction>(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_func->basic_blocks.push_back(new_block);
|
||||||
cur_block = new_block;
|
cur_block = new_block;
|
||||||
auto phi_act = std::make_shared<PhiItem>();
|
|
||||||
phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
phi_act->ty = LLVMIRIntType(1);
|
phi_act->ty = LLVMIRIntType(1);
|
||||||
phi_act->values.push_back(std::make_pair("0", src_block->label_full));
|
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++;
|
size_t new_block_id = block_counter++;
|
||||||
auto right_cal_block = std::make_shared<BlockItem>();
|
auto right_cal_block = std::make_shared<BlockItem>();
|
||||||
auto new_block = std::make_shared<BlockItem>();
|
auto new_block = std::make_shared<BlockItem>();
|
||||||
|
auto phi_act = std::make_shared<PhiItem>();
|
||||||
|
|
||||||
right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id);
|
right_cal_block->label_full = "label_" + std::to_string(right_cal_block_id);
|
||||||
new_block->label_full = "label_" + std::to_string(new_block_id);
|
new_block->label_full = "label_" + std::to_string(new_block_id);
|
||||||
cur_block->exit_action = std::make_shared<BRAction>();
|
cur_block->exit_action = std::make_shared<BRAction>();
|
||||||
@ -996,15 +1004,18 @@ void IRBuilder::ActuralVisit(LOrExpr_ASTNode *node) {
|
|||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->true_label_full = new_block->label_full;
|
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->true_label_full = new_block->label_full;
|
||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->false_label_full = right_cal_block->label_full;
|
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->false_label_full = right_cal_block->label_full;
|
||||||
std::dynamic_pointer_cast<BRAction>(cur_block->exit_action)->cond = node->left->IR_result_full;
|
std::dynamic_pointer_cast<BRAction>(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_func->basic_blocks.push_back(right_cal_block);
|
||||||
cur_block = right_cal_block;
|
cur_block = right_cal_block;
|
||||||
node->right->accept(this);
|
node->right->accept(this);
|
||||||
cur_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
cur_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
||||||
auto right_block_end = cur_block;
|
auto right_block_end = cur_block;
|
||||||
std::dynamic_pointer_cast<UNConditionJMPAction>(cur_block->exit_action)->label_full = new_block->label_full;
|
std::dynamic_pointer_cast<UNConditionJMPAction>(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_func->basic_blocks.push_back(new_block);
|
||||||
cur_block = new_block;
|
cur_block = new_block;
|
||||||
auto phi_act = std::make_shared<PhiItem>();
|
|
||||||
phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
phi_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
phi_act->ty = LLVMIRIntType(1);
|
phi_act->ty = LLVMIRIntType(1);
|
||||||
phi_act->values.push_back(std::make_pair("1", src_block->label_full));
|
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");
|
ExprTypeInfo void_std = IdentifierType("void");
|
||||||
if (node->expr_type_info != void_std) {
|
if (node->expr_type_info != void_std) {
|
||||||
auto phi_act = std::make_shared<PhiItem>();
|
auto phi_act = std::make_shared<PhiItem>();
|
||||||
|
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->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
|
||||||
phi_act->ty = Type_AST2LLVM(node->expr_type_info);
|
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));
|
phi_act->values.push_back(std::make_pair(node->src1->IR_result_full, src1_end_block->label_full));
|
||||||
|
@ -28,8 +28,8 @@ 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);
|
IR->RecursivePrint(std::cerr);
|
||||||
// GenerateNaiveASM(fout, IR);
|
GenerateNaiveASM(fout, IR);
|
||||||
} catch (const SemanticError &err) {
|
} catch (const SemanticError &err) {
|
||||||
std::cout << err.what() << std::endl;
|
std::cout << err.what() << std::endl;
|
||||||
return err.GetErrorCode();
|
return err.GetErrorCode();
|
||||||
|
@ -1,4 +1,59 @@
|
|||||||
#include "naivebackend.h"
|
#include "naivebackend.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "IR/IR_basic.h"
|
||||||
|
#include "build_layout.hpp"
|
||||||
|
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>();
|
||||||
|
|
||||||
|
for (auto conststr : prog->const_strs) {
|
||||||
|
auto asm_item = std::make_shared<RISCVConstStrItem>();
|
||||||
|
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<RISCVGlobalVarItem>();
|
||||||
|
riscv->global_vars.push_back(asm_item);
|
||||||
|
asm_item->full_label = ".var.global." + global_var->name_raw + ".addrkp";
|
||||||
|
}
|
||||||
|
std::unordered_map<std::string, FuncLayout> 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<RISCVFuncItem>();
|
||||||
|
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);
|
||||||
}
|
}
|
Reference in New Issue
Block a user