Commit e547371b authored by Yang's avatar Yang

add codegen summary

parent c396901a
......@@ -3,15 +3,15 @@
{
"type": "lldb",
"request": "launch",
"name": "Compile & Debug 1.ll",
"name": "Compile & Gen 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-o",
"./build/1.ll",
"-emit-llvm",
"./build/1.cminus"
"./build/1.cminus",
"-o",
"./build/1.ll"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
......@@ -24,21 +24,42 @@
{
"type": "lldb",
"request": "launch",
"name": "Debug 1.ll",
"name": "Gen 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-o",
"./build/1.ll",
"-emit-llvm",
"./build/1.cminus"
"./build/1.cminus",
"-o",
"./build/1.ll"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
"initCommands": [
"command script import ${workspaceFolder}/lldb_formatters.py"
]
},
{
"type": "lldb",
"request": "launch",
"name": "Compile & Gen 1.s",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-S",
"./build/1.cminus",
"-o",
"./build/1.s"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
// 程序运行前运行的命令(例如 build)
"preLaunchTask": "make cminusfc",
"initCommands": [
"command script import ${workspaceFolder}/lldb_formatters.py"
]
}
]
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
#include <string>
struct ASMInstruction {
enum InstType { Instruction, Atrribute, Label, Comment } type;
enum InstType { Instruction, Attribute, Label, Comment } type;
std::string content;
explicit ASMInstruction(std::string s, InstType ty = Instruction)
......@@ -13,7 +13,7 @@ struct ASMInstruction {
std::string format() const {
switch (type) {
case ASMInstruction::Instruction:
case ASMInstruction::Atrribute:
case ASMInstruction::Attribute:
return "\t" + content + "\n";
case ASMInstruction::Label:
return content + ":\n";
......@@ -22,4 +22,7 @@ struct ASMInstruction {
}
assert(false && "unreachable");
}
// 用于 lldb 调试生成 summary
std::string safe_print() const;
};
......@@ -8,13 +8,16 @@
class CodeGen {
public:
explicit CodeGen(Module *module) : m(module) {}
~CodeGen(){
for(auto i : output) delete i;
}
std::string print() const;
void run();
template <class... Args> void append_inst(Args... arg) {
output.emplace_back(arg...);
output.emplace_back(new ASMInstruction(arg...));
}
void
......@@ -26,7 +29,7 @@ class CodeGen {
}
content.pop_back();
content.pop_back();
output.emplace_back(content, ty);
output.emplace_back(new ASMInstruction(content, ty));
}
private:
......@@ -98,5 +101,5 @@ class CodeGen {
} context;
Module *m;
std::list<ASMInstruction> output;
std::list<ASMInstruction*> output;
};
......@@ -32,6 +32,9 @@ struct Reg {
std::string print() const;
// 用于 lldb 调试生成 summary
std::string safe_print() const;
static Reg zero() { return Reg(0); }
static Reg ra() { return Reg(1); }
static Reg sp() { return Reg(3); }
......@@ -62,17 +65,20 @@ struct FReg {
std::string print() const;
static FReg fa(unsigned i) {
assert(0 <= i and i <= 7);
assert(i <= 7);
return FReg(i);
}
static FReg ft(unsigned i) {
assert(0 <= i and i <= 15);
assert(i <= 15);
return FReg(i + 8);
}
static FReg fs(unsigned i) {
assert(0 <= i and i <= 7);
assert(i <= 7);
return FReg(i + 24);
}
// 用于 lldb 调试生成 summary
std::string safe_print() const;
};
struct CFReg {
......@@ -82,4 +88,7 @@ struct CFReg {
bool operator==(const CFReg &other) { return id == other.id; }
std::string print() const { return "$fcc" + std::to_string(id); }
// 用于 lldb 调试生成 summary
std::string safe_print() const;
};
......@@ -40,7 +40,7 @@ class Function : public Value {
BasicBlock *get_entry_block() const { return basic_blocks_.front(); }
std::list<BasicBlock*> &get_basic_blocks() { return basic_blocks_; }
std::list<Argument> &get_args() { return arguments_; }
std::list<Argument*> &get_args() { return arguments_; }
bool is_declaration() const { return basic_blocks_.empty(); }
......@@ -58,7 +58,7 @@ class Function : public Value {
private:
std::list<BasicBlock*> basic_blocks_;
std::list<Argument> arguments_;
std::list<Argument*> arguments_;
Module *parent_;
unsigned seq_cnt_; // print use
};
......
......@@ -6,8 +6,8 @@
class Names
{
public:
explicit Names(bool use_underline, std::string prefix, std::string append)
: use_underline_(use_underline), default_prefix_used_count_(0), default_prefix_(std::move(prefix)),
explicit Names(std::string prefix, std::string append)
: default_prefix_used_count_(0), default_prefix_(std::move(prefix)),
appended_prefix_(std::move(append))
{
}
......@@ -18,7 +18,6 @@ public:
std::string get_name();
private:
bool use_underline_;
int default_prefix_used_count_;
std::string default_prefix_;
std::string appended_prefix_;
......
......@@ -9,7 +9,13 @@ def parseString(val : lldb.SBValue):
return ""
def SafePrintSummary(valobj: lldb.SBValue, internal_dict):
name: lldb.SBValue = valobj.EvaluateExpression("this->safe_print()")
if valobj.GetType().IsPointerType():
deref: lldb.SBValue = valobj.Dereference()
if deref.IsValid():
valobj = deref
else:
return ""
name: lldb.SBValue = valobj.EvaluateExpression("safe_print()")
return parseString(name)
def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
......@@ -18,7 +24,8 @@ def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
, "Function", "Argument"
, "BasicBlock"
, "GlobalVariable"
, "Instruction", "IBinaryInst", "FBinaryInst", "ICmpInst", "FCmpInst", "CallInst", "BranchInst", "ReturnInst", "GetElementPtrInst", "StoreInst", "LoadInst", "AllocaInst", "ZextInst", "FpToSiInst", "SiToFpInst", "PhiInst" ]
, "Instruction", "IBinaryInst", "FBinaryInst", "ICmpInst", "FCmpInst", "CallInst", "BranchInst", "ReturnInst", "GetElementPtrInst", "StoreInst", "LoadInst", "AllocaInst", "ZextInst", "FpToSiInst", "SiToFpInst", "PhiInst"
, "ASMInstruction", "Reg", "FReg", "CFReg" ]
for i in types:
debugger.HandleCommand(
f"type summary add -F lldb_formatters.SafePrintSummary {i} -w my"
......
......@@ -142,8 +142,8 @@ Value* CminusfBuilder::visit(ASTFunDeclaration &node) {
scope.enter();
context.pre_enter_scope = true;
std::vector<Value *> args;
for (auto &arg : func->get_args()) {
args.push_back(&arg);
for (auto arg : func->get_args()) {
args.push_back(arg);
}
for (unsigned int i = 0; i < node.params.size(); ++i) {
if (node.params[i]->isarray) {
......
#include "CodeGen.hpp"
#include "ASMInstruction.hpp"
#include "CodeGenUtil.hpp"
#include "Register.hpp"
std::string ASMInstruction::safe_print() const
{
switch (type) {
case Instruction:
case Attribute:
return content;
case Label:
return content + ":";
case Comment:
return "# " + content;
}
return "<error>";
}
void CodeGen::allocate() {
// 备份 $ra $fp
......@@ -8,9 +24,9 @@ void CodeGen::allocate() {
// 为每个参数分配栈空间
for (auto &arg : context.func->get_args()) {
auto size = arg.get_type()->get_size();
auto size = arg->get_type()->get_size();
offset = offset + size;
context.offset_map[&arg] = -static_cast<int>(offset);
context.offset_map[arg] = -static_cast<int>(offset);
}
// 为指令结果分配栈空间
......@@ -205,11 +221,11 @@ void CodeGen::gen_prologue() {
int garg_cnt = 0;
int farg_cnt = 0;
for (auto &arg : context.func->get_args()) {
if (arg.get_type()->is_float_type()) {
store_from_freg(&arg, FReg::fa(farg_cnt++));
for (auto arg : context.func->get_args()) {
if (arg->get_type()->is_float_type()) {
store_from_freg(arg, FReg::fa(farg_cnt++));
} else { // int or pointer
store_from_greg(&arg, Reg::a(garg_cnt++));
store_from_greg(arg, Reg::a(garg_cnt++));
}
}
}
......@@ -241,16 +257,16 @@ void CodeGen::gen_binary() {
load_to_greg(context.inst->get_operand(1), Reg::t(1));
switch (context.inst->get_instr_type()) {
case Instruction::add:
output.emplace_back("add.w $t2, $t0, $t1");
append_inst("add.w $t2, $t0, $t1");
break;
case Instruction::sub:
output.emplace_back("sub.w $t2, $t0, $t1");
append_inst("sub.w $t2, $t0, $t1");
break;
case Instruction::mul:
output.emplace_back("mul.w $t2, $t0, $t1");
append_inst("mul.w $t2, $t0, $t1");
break;
case Instruction::sdiv:
output.emplace_back("div.w $t2, $t0, $t1");
append_inst("div.w $t2, $t0, $t1");
break;
default:
assert(false);
......@@ -370,26 +386,26 @@ void CodeGen::run() {
* - 支持更旧版本的 GNU 汇编器, 因为 `.bss` 伪指令是应该相对较新的指令,
* GNU 汇编器在 2023 年 2 月的 2.37 版本才将其引入
*/
append_inst(".text", ASMInstruction::Atrribute);
append_inst(".text", ASMInstruction::Attribute);
append_inst(".section", {".bss", "\"aw\"", "@nobits"},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
for (auto global : m->get_global_variable()) {
auto size =
global->get_type()->get_pointer_element_type()->get_size();
append_inst(".globl", {global->get_name()},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
append_inst(".type", {global->get_name(), "@object"},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
append_inst(".size", {global->get_name(), std::to_string(size)},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
append_inst(global->get_name(), ASMInstruction::Label);
append_inst(".space", {std::to_string(size)},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
}
}
// 函数代码段
output.emplace_back(".text", ASMInstruction::Atrribute);
output.emplace_back(new ASMInstruction(".text", ASMInstruction::Attribute));
for (auto func : m->get_functions()) {
if (not func->is_declaration()) {
// 更新 context
......@@ -397,9 +413,9 @@ void CodeGen::run() {
context.func = func;
// 函数信息
append_inst(".globl", {func->get_name()}, ASMInstruction::Atrribute);
append_inst(".globl", {func->get_name()}, ASMInstruction::Attribute);
append_inst(".type", {func->get_name(), "@function"},
ASMInstruction::Atrribute);
ASMInstruction::Attribute);
append_inst(func->get_name(), ASMInstruction::Label);
// 分配函数栈帧
......@@ -495,8 +511,8 @@ void CodeGen::run() {
std::string CodeGen::print() const {
std::string result;
for (const auto &inst : output) {
result += inst.format();
for (const auto inst : output) {
result += inst->format();
}
return result;
}
......@@ -26,9 +26,35 @@ std::string Reg::print() const {
assert(false);
}
std::string Reg::safe_print() const
{
if (id == 0) {
return "$zero";
}
if (id == 1) {
return "$ra";
}
if (id == 2) {
return "$tp";
}
if (id == 3) {
return "$sp";
}
if (4 <= id and id <= 11) {
return "$a" + std::to_string(id - 4);
}
if (12 <= id and id <= 20) {
return "$t" + std::to_string(id - 12);
}
if (id == 22) {
return "$fp";
}
return "<error id " + std::to_string(id) + ">";
}
std::string FReg::print() const {
if (0 <= id and id <= 7) {
if (id <= 7) {
return "$fa" + std::to_string(id);
}
if (8 <= id and id <= 23) {
......@@ -39,3 +65,22 @@ std::string FReg::print() const {
}
assert(false);
}
std::string FReg::safe_print() const
{
if (id <= 7) {
return "$fa" + std::to_string(id);
}
if (8 <= id and id <= 23) {
return "$ft" + std::to_string(id - 8);
}
if (24 <= id and id <= 31) {
return "$fs" + std::to_string(id - 24);
}
return "<error id " + std::to_string(id) + ">";
}
std::string CFReg::safe_print() const
{
return "$fcc" + std::to_string(id);
}
......@@ -125,4 +125,4 @@ BasicBlock* BasicBlock::get_entry_block_of_same_function() const
return parent_->get_entry_block();
}
Names GLOBAL_BASICBLOCK_NAMES_{false, "label", ""};
\ No newline at end of file
Names GLOBAL_BASICBLOCK_NAMES_{"label", "_"};
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include "Module.hpp"
#include "Instruction.hpp"
#include <cassert>
#include <string>
#include <unordered_set>
#include <queue>
......@@ -10,24 +11,25 @@ namespace
{
std::string chopName(std::string name)
{
if (name.size() > 4) return { name.begin(), name.begin() + 4 };
if (name.size() > 3) return { name.begin(), name.begin() + 3 };
return name;
}
}
Function::Function(FunctionType* ty, const std::string& name, Module* parent)
: Value(ty, name), names4blocks_(false, "label", chopName(name)), names4insts_(true, "op", ""), parent_(parent), seq_cnt_(0) {
: Value(ty, name), names4blocks_("label", chopName(name) + "_"), names4insts_("op", ""), parent_(parent), seq_cnt_(0) {
// num_args_ = ty->getNumParams();
parent->add_function(this);
// build args
for (unsigned i = 0; i < get_num_of_args(); i++) {
arguments_.emplace_back(ty->get_param_type(i), "", this, i);
arguments_.emplace_back(new Argument(ty->get_param_type(i), "arg" + std::to_string(i), this, i));
}
}
Function::~Function()
{
for (auto bb : basic_blocks_) delete bb;
for(auto arg: arguments_) delete arg;
}
Function* Function::create(FunctionType* ty, const std::string& name,
......@@ -66,10 +68,10 @@ void Function::add_basic_block(BasicBlock* bb) { basic_blocks_.push_back(bb); }
void Function::set_instr_name() {
std::map<Value*, int> seq;
for (auto& arg : this->get_args()) {
if (seq.find(&arg) == seq.end()) {
if (seq.find(arg) == seq.end()) {
auto seq_num = seq.size() + seq_cnt_;
if (arg.set_name("arg" + std::to_string(seq_num))) {
seq.insert({ &arg, seq_num });
if (arg->set_name("arg" + std::to_string(seq_num))) {
seq.insert({ arg, seq_num });
}
}
}
......@@ -121,7 +123,7 @@ std::string Function::print() {
for (auto& arg : get_args()) {
if (&arg != &*get_args().begin())
func_ir += ", ";
func_ir += arg.print();
func_ir += arg->print();
}
}
func_ir += ")";
......@@ -160,7 +162,7 @@ std::string Argument::safe_print() const
auto ty = parent->get_function_type();
if (ty == nullptr || ty->get_num_of_args() <= arg_no_) return "@" + parent->get_name() + " arg" + std::to_string(arg_no_) + " <unknow type>";
auto ty2 = ty->get_param_type(arg_no_);
return "@" + parent->get_name() + " arg" + std::to_string(arg_no_) + " " + (ty2 == nullptr ? "<null>" : ty2->safe_print());
return (ty2 == nullptr ? "<null>" : ty2->safe_print()) + " @" + parent->get_name() + " arg" + std::to_string(arg_no_);
}
......
......@@ -538,10 +538,12 @@ std::string BranchInst::print() {
std::string ReturnInst::print() {
std::string instr_ir;
instr_ir += safe_print_instr_op_name(get_instr_type());
instr_ir += get_instr_op_name();
instr_ir += " ";
if (!is_void_ret()) {
instr_ir += safe_print_op_as_op(this, 0, true);
instr_ir += this->get_operand(0)->get_type()->print();
instr_ir += " ";
instr_ir += print_as_op(this->get_operand(0), false);
} else {
instr_ir += "void";
}
......
......@@ -368,4 +368,4 @@ PhiInst *PhiInst::create_phi(Type *ty, BasicBlock *bb,
return new PhiInst(ty, vals, val_bbs, bb, name);
}
Names GLOBAL_INSTRUCTION_NAMES_{ true, "op", "" };
\ No newline at end of file
Names GLOBAL_INSTRUCTION_NAMES_{"op", "_" };
\ No newline at end of file
......@@ -3,19 +3,25 @@
std::string Names::get_name(std::string name)
{
int ed = static_cast<int>(name.size());
while (ed > 0)
int bg = 0;
while (bg < ed)
{
char ch = name[bg];
if (ch == '_' || (ch >= '0' && ch <= '9')) bg++;
else break;
}
while (ed > bg)
{
char ch = name[ed - 1];
if ((use_underline_ && ch == '_') || (ch >= '0' && ch <= '9')) ed--;
if (ch == '_' || (ch >= '0' && ch <= '9')) ed--;
else break;
}
if (ed == 0) return get_name();
std::string name1 = {name.begin(), name.begin() + ed};
if (bg == ed) return get_name();
std::string name1 = {name.begin() + bg, name.begin() + ed};
if (name1 == default_prefix_) return get_name();
auto get = appended_prefix_ + name1;
auto idx = allocated_[name1]++;
if (idx == 0) return get;
if (use_underline_) get += "_";
return get + std::to_string(idx);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment