Commit e547371b authored by Yang's avatar Yang

add codegen summary

parent c396901a
{
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Compile & Debug 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-o",
"./build/1.ll",
"-emit-llvm",
"./build/1.cminus"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
// 程序运行前运行的命令(例如 build)
"preLaunchTask": "make cminusfc",
"initCommands": [
"command script import ${workspaceFolder}/lldb_formatters.py"
]
},
{
"type": "lldb",
"request": "launch",
"name": "Debug 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-o",
"./build/1.ll",
"-emit-llvm",
"./build/1.cminus"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
"initCommands": [
"command script import ${workspaceFolder}/lldb_formatters.py"
]
}
]
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Compile & Gen 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-emit-llvm",
"./build/1.cminus",
"-o",
"./build/1.ll"
],
// 程序运行的目录
"cwd": "${workspaceFolder}",
// 程序运行前运行的命令(例如 build)
"preLaunchTask": "make cminusfc",
"initCommands": [
"command script import ${workspaceFolder}/lldb_formatters.py"
]
},
{
"type": "lldb",
"request": "launch",
"name": "Gen 1.ll",
// 要调试的程序
"program": "${workspaceFolder}/build/cminusfc",
// 命令行参数
"args": [
"-emit-llvm",
"./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
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "make cminusfc",
"command": "cd build && make"
}
]
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "make cminusfc",
"command": "cd build && make"
}
]
}
\ No newline at end of file
......@@ -12,17 +12,17 @@ SET(CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fsaniti
set(default_build_type "Debug")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag("-fstandalone-debug" CXX_SUPPORTS_STANDALONE_DEBUG)
if(CXX_SUPPORTS_STANDALONE_DEBUG)
message(STATUS "Adding -fstandalone-debug for Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstandalone-debug")
else()
message(STATUS "Clang does not support -fstandalone-debug, skipping")
endif()
else()
message(STATUS "Use Gcc")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag("-fstandalone-debug" CXX_SUPPORTS_STANDALONE_DEBUG)
if(CXX_SUPPORTS_STANDALONE_DEBUG)
message(STATUS "Adding -fstandalone-debug for Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstandalone-debug")
else()
message(STATUS "Clang does not support -fstandalone-debug, skipping")
endif()
else()
message(STATUS "Use Gcc")
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
......
......@@ -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;
};
......@@ -90,23 +90,23 @@ struct ASTNode {
};
struct ASTProgram : ASTNode {
Value* accept(ASTVisitor &) final;
~ASTProgram() override = default;
Value* accept(ASTVisitor &) final;
~ASTProgram() override = default;
std::vector<std::shared_ptr<ASTDeclaration>> declarations;
};
struct ASTDeclaration : ASTNode {
~ASTDeclaration() override = default;
~ASTDeclaration() override = default;
CminusType type;
std::string id;
};
struct ASTFactor : ASTNode {
~ASTFactor() override = default;
~ASTFactor() override = default;
};
struct ASTNum : ASTFactor {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
CminusType type;
union {
int i_val;
......@@ -115,18 +115,18 @@ struct ASTNum : ASTFactor {
};
struct ASTVarDeclaration : ASTDeclaration {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTNum> num;
};
struct ASTFunDeclaration : ASTDeclaration {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::vector<std::shared_ptr<ASTParam>> params;
std::shared_ptr<ASTCompoundStmt> compound_stmt;
};
struct ASTParam : ASTNode {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
CminusType type;
std::string id;
// true if it is array param
......@@ -134,22 +134,22 @@ struct ASTParam : ASTNode {
};
struct ASTStatement : ASTNode {
~ASTStatement() override = default;
~ASTStatement() override = default;
};
struct ASTCompoundStmt : ASTStatement {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::vector<std::shared_ptr<ASTVarDeclaration>> local_declarations;
std::vector<std::shared_ptr<ASTStatement>> statement_list;
};
struct ASTExpressionStmt : ASTStatement {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTExpression> expression;
};
struct ASTSelectionStmt : ASTStatement {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTExpression> expression;
std::shared_ptr<ASTStatement> if_statement;
// should be nullptr if no else structure exists
......@@ -157,13 +157,13 @@ struct ASTSelectionStmt : ASTStatement {
};
struct ASTIterationStmt : ASTStatement {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTExpression> expression;
std::shared_ptr<ASTStatement> statement;
};
struct ASTReturnStmt : ASTStatement {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
// should be nullptr if return void
std::shared_ptr<ASTExpression> expression;
};
......@@ -171,41 +171,41 @@ struct ASTReturnStmt : ASTStatement {
struct ASTExpression : ASTFactor {};
struct ASTAssignExpression : ASTExpression {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTVar> var;
std::shared_ptr<ASTExpression> expression;
};
struct ASTSimpleExpression : ASTExpression {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTAdditiveExpression> additive_expression_l;
std::shared_ptr<ASTAdditiveExpression> additive_expression_r;
RelOp op;
};
struct ASTVar : ASTFactor {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::string id;
// nullptr if var is of int type
std::shared_ptr<ASTExpression> expression;
};
struct ASTAdditiveExpression : ASTNode {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTAdditiveExpression> additive_expression;
AddOp op;
std::shared_ptr<ASTTerm> term;
};
struct ASTTerm : ASTNode {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::shared_ptr<ASTTerm> term;
MulOp op;
std::shared_ptr<ASTFactor> factor;
};
struct ASTCall : ASTFactor {
Value* accept(ASTVisitor &) final;
Value* accept(ASTVisitor &) final;
std::string id;
std::vector<std::shared_ptr<ASTExpression>> args;
};
......@@ -233,22 +233,22 @@ class ASTVisitor {
class ASTPrinter : public ASTVisitor {
public:
Value* visit(ASTProgram &) final;
Value* visit(ASTNum &) final;
Value* visit(ASTVarDeclaration &) final;
Value* visit(ASTFunDeclaration &) final;
Value* visit(ASTParam &) final;
Value* visit(ASTCompoundStmt &) final;
Value* visit(ASTExpressionStmt &) final;
Value* visit(ASTSelectionStmt &) final;
Value* visit(ASTIterationStmt &) final;
Value* visit(ASTReturnStmt &) final;
Value* visit(ASTAssignExpression &) final;
Value* visit(ASTSimpleExpression &) final;
Value* visit(ASTAdditiveExpression &) final;
Value* visit(ASTVar &) final;
Value* visit(ASTTerm &) final;
Value* visit(ASTCall &) final;
Value* visit(ASTProgram &) final;
Value* visit(ASTNum &) final;
Value* visit(ASTVarDeclaration &) final;
Value* visit(ASTFunDeclaration &) final;
Value* visit(ASTParam &) final;
Value* visit(ASTCompoundStmt &) final;
Value* visit(ASTExpressionStmt &) final;
Value* visit(ASTSelectionStmt &) final;
Value* visit(ASTIterationStmt &) final;
Value* visit(ASTReturnStmt &) final;
Value* visit(ASTAssignExpression &) final;
Value* visit(ASTSimpleExpression &) final;
Value* visit(ASTAdditiveExpression &) final;
Value* visit(ASTVar &) final;
Value* visit(ASTTerm &) final;
Value* visit(ASTCall &) final;
void add_depth() { depth += 2; }
void remove_depth() { depth -= 2; }
......
......@@ -12,10 +12,10 @@ class Module;
class BasicBlock : public Value {
public:
BasicBlock(const BasicBlock& other) = delete;
BasicBlock(BasicBlock&& other) noexcept = delete;
BasicBlock& operator=(const BasicBlock& other) = delete;
BasicBlock& operator=(BasicBlock&& other) noexcept = delete;
BasicBlock(const BasicBlock& other) = delete;
BasicBlock(BasicBlock&& other) noexcept = delete;
BasicBlock& operator=(const BasicBlock& other) = delete;
BasicBlock& operator=(BasicBlock&& other) noexcept = delete;
~BasicBlock() override;
static BasicBlock *create(Module *m, const std::string &name,
Function *parent) {
......@@ -31,18 +31,18 @@ class BasicBlock : public Value {
void add_pre_basic_block(BasicBlock *bb)
{
for (auto i : pre_bbs_) if (i == bb) return;
pre_bbs_.push_back(bb);
pre_bbs_.push_back(bb);
}
// 自动去重
void add_succ_basic_block(BasicBlock *bb)
{
for (auto i : succ_bbs_) if (i == bb) return;
succ_bbs_.push_back(bb);
succ_bbs_.push_back(bb);
}
void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); }
// 若你将 br label0, label0 的其中一个 label0 改为 label1,并且调用 remove_suc label0,那 suc 集合中也将不再包含 label0
void remove_succ_basic_block(BasicBlock *bb) { succ_bbs_.remove(bb); }
BasicBlock* get_entry_block_of_same_function() const;
BasicBlock* get_entry_block_of_same_function() const;
// If the Block is terminated by ret/br
bool is_terminated() const;
......@@ -77,7 +77,7 @@ class BasicBlock : public Value {
Module *get_module() const;
void erase_from_parent();
std::string print() override;
std::string print() override;
// 用于 lldb 调试生成 summary
std::string safe_print() const;
......
......@@ -56,7 +56,7 @@ class ConstantArray : public Constant {
static ConstantArray *get(ArrayType *ty,
const std::vector<Constant *> &val);
std::string print() override;
std::string print() override;
};
class ConstantZero : public Constant {
......
......@@ -16,10 +16,10 @@ class FunctionType;
class Function : public Value {
public:
Function(const Function& other) = delete;
Function(Function&& other) noexcept = delete;
Function& operator=(const Function& other) = delete;
Function& operator=(Function&& other) noexcept = delete;
Function(const Function& other) = delete;
Function(Function&& other) noexcept = delete;
Function& operator=(const Function& other) = delete;
Function& operator=(Function&& other) noexcept = delete;
Function(FunctionType *ty, const std::string &name, Module *parent);
~Function() override;
static Function *create(FunctionType *ty, const std::string &name,
......@@ -35,18 +35,18 @@ class Function : public Value {
Module *get_parent() const;
// 此处 remove 的 BasicBlock, 需要手动 delete
// 此处 remove 的 BasicBlock, 需要手动 delete
void remove(BasicBlock *bb);
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(); }
void set_instr_name();
std::string print() override;
// 用于检查函数的基本块是否存在问题
// 用于检查函数的基本块是否存在问题
void check_for_block_relation_error() const;
// 用于 lldb 调试生成 summary
......@@ -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
};
......@@ -66,17 +66,17 @@ class Function : public Value {
// Argument of Function, does not contain actual value
class Argument : public Value {
public:
Argument(const Argument& other) = delete;
Argument(Argument&& other) noexcept = delete;
Argument& operator=(const Argument& other) = delete;
Argument& operator=(Argument&& other) noexcept = delete;
Argument(const Argument& other) = delete;
Argument(Argument&& other) noexcept = delete;
Argument& operator=(const Argument& other) = delete;
Argument& operator=(Argument&& other) noexcept = delete;
explicit Argument(Type *ty, const std::string &name = "",
Function *f = nullptr, unsigned arg_no = 0)
: Value(ty, name), parent_(f), arg_no_(arg_no) {}
~Argument() override = default;
~Argument() override = default;
const Function *get_parent() const { return parent_; }
Function *get_parent() { return parent_; }
const Function *get_parent() const { return parent_; }
Function *get_parent() { return parent_; }
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
unsigned get_arg_no() const {
......@@ -84,7 +84,7 @@ class Argument : public Value {
return arg_no_;
}
std::string print() override;
std::string print() override;
// 用于 lldb 调试生成 summary
std::string safe_print() const;
......
......@@ -277,7 +277,7 @@ class AllocaInst : public Instruction {
public:
// 新特性:指令表分为 {alloca, phi | other inst} 两段,创建和向基本块插入 alloca 和 phi,都只会插在第一段,它们在常规指令前面
static AllocaInst *create_alloca(Type *ty, BasicBlock *bb, const std::string& name = "");
Type *get_alloca_type() const {
return get_type()->get_pointer_element_type();
}
......
......@@ -42,7 +42,7 @@ class Module {
private:
// The global variables in the module
std::list<GlobalVariable*> global_list_;
std::list<GlobalVariable*> global_list_;
// The functions in the module
std::list<Function*> function_list_;
......
......@@ -6,22 +6,21 @@
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)),
appended_prefix_(std::move(append))
{
}
explicit Names(std::string prefix, std::string append)
: default_prefix_used_count_(0), default_prefix_(std::move(prefix)),
appended_prefix_(std::move(append))
{
}
// 获得一个 Names 内唯一的名称,会保持唯一的同时尽可能的与 names 类似
std::string get_name(std::string name);
// 获得一个 Names 内唯一的名称
std::string get_name();
// 获得一个 Names 内唯一的名称,会保持唯一的同时尽可能的与 names 类似
std::string get_name(std::string name);
// 获得一个 Names 内唯一的名称
std::string get_name();
private:
bool use_underline_;
int default_prefix_used_count_;
std::string default_prefix_;
std::string appended_prefix_;
std::unordered_map<std::string, int> allocated_;
int default_prefix_used_count_;
std::string default_prefix_;
std::string appended_prefix_;
std::unordered_map<std::string, int> allocated_;
};
#endif // !NAMES_HPP
......@@ -12,12 +12,12 @@ class FloatType;
class Type {
public:
Type(const Type& other) = delete;
Type(Type&& other) noexcept = delete;
Type& operator=(const Type& other) = delete;
Type& operator=(Type&& other) noexcept = delete;
Type(const Type& other) = delete;
Type(Type&& other) noexcept = delete;
Type& operator=(const Type& other) = delete;
Type& operator=(Type&& other) noexcept = delete;
enum TypeID: uint8_t {
enum TypeID: uint8_t {
VoidTyID, // Void
LabelTyID, // Labels, e.g., BasicBlock
IntegerTyID, // Integers, include 32 bits and 1 bit
......@@ -63,12 +63,12 @@ class Type {
class IntegerType : public Type {
public:
IntegerType(const IntegerType& other) = delete;
IntegerType(IntegerType&& other) noexcept = delete;
IntegerType& operator=(const IntegerType& other) = delete;
IntegerType& operator=(IntegerType&& other) noexcept = delete;
IntegerType(const IntegerType& other) = delete;
IntegerType(IntegerType&& other) noexcept = delete;
IntegerType& operator=(const IntegerType& other) = delete;
IntegerType& operator=(IntegerType&& other) noexcept = delete;
explicit IntegerType(unsigned num_bits, Module *m);
explicit IntegerType(unsigned num_bits, Module *m);
~IntegerType() override;
unsigned get_num_bits() const;
......@@ -79,12 +79,12 @@ class IntegerType : public Type {
class FunctionType : public Type {
public:
FunctionType(const FunctionType& other) = delete;
FunctionType(FunctionType&& other) noexcept = delete;
FunctionType& operator=(const FunctionType& other) = delete;
FunctionType& operator=(FunctionType&& other) noexcept = delete;
FunctionType(const FunctionType& other) = delete;
FunctionType(FunctionType&& other) noexcept = delete;
FunctionType& operator=(const FunctionType& other) = delete;
FunctionType& operator=(FunctionType&& other) noexcept = delete;
FunctionType(Type *result, const std::vector<Type *>& params);
FunctionType(Type *result, const std::vector<Type *>& params);
~FunctionType() override;
static bool is_valid_return_type(const Type *ty);
......@@ -106,12 +106,12 @@ class FunctionType : public Type {
class ArrayType : public Type {
public:
ArrayType(const ArrayType& other) = delete;
ArrayType(ArrayType&& other) noexcept = delete;
ArrayType& operator=(const ArrayType& other) = delete;
ArrayType& operator=(ArrayType&& other) noexcept = delete;
ArrayType(const ArrayType& other) = delete;
ArrayType(ArrayType&& other) noexcept = delete;
ArrayType& operator=(const ArrayType& other) = delete;
ArrayType& operator=(ArrayType&& other) noexcept = delete;
ArrayType(Type *contained, unsigned num_elements);
ArrayType(Type *contained, unsigned num_elements);
~ArrayType() override;
static bool is_valid_element_type(const Type *ty);
......@@ -128,12 +128,12 @@ class ArrayType : public Type {
class PointerType : public Type {
public:
PointerType(const PointerType& other) = delete;
PointerType(PointerType&& other) noexcept = delete;
PointerType& operator=(const PointerType& other) = delete;
PointerType& operator=(PointerType&& other) noexcept = delete;
PointerType(const PointerType& other) = delete;
PointerType(PointerType&& other) noexcept = delete;
PointerType& operator=(const PointerType& other) = delete;
PointerType& operator=(PointerType&& other) noexcept = delete;
PointerType(Type *contained);
PointerType(Type *contained);
~PointerType() override;
Type *get_element_type() const { return contained_; }
......@@ -145,12 +145,12 @@ class PointerType : public Type {
class FloatType : public Type {
public:
FloatType(const FloatType& other) = delete;
FloatType(FloatType&& other) noexcept = delete;
FloatType& operator=(const FloatType& other) = delete;
FloatType& operator=(FloatType&& other) noexcept = delete;
FloatType(const FloatType& other) = delete;
FloatType(FloatType&& other) noexcept = delete;
FloatType& operator=(const FloatType& other) = delete;
FloatType& operator=(FloatType&& other) noexcept = delete;
FloatType(Module *m);
FloatType(Module *m);
~FloatType() override;
static FloatType *get(Module *m);
};
......@@ -6,11 +6,11 @@
class User : public Value {
public:
User(const User& other) = delete;
User(User&& other) noexcept = delete;
User& operator=(const User& other) = delete;
User& operator=(User&& other) noexcept = delete;
User(Type *ty, const std::string &name = "") : Value(ty, name){}
User(const User& other) = delete;
User(User&& other) noexcept = delete;
User& operator=(const User& other) = delete;
User& operator=(User&& other) noexcept = delete;
User(Type *ty, const std::string &name = "") : Value(ty, name){}
~User() override;
const std::vector<Value *> &get_operands() const { return operands_; }
......
......@@ -12,12 +12,12 @@ struct Use;
class Value {
public:
Value(const Value& other) = delete;
Value(Value&& other) noexcept = delete;
Value& operator=(const Value& other) = delete;
Value& operator=(Value&& other) noexcept = delete;
Value(const Value& other) = delete;
Value(Value&& other) noexcept = delete;
Value& operator=(const Value& other) = delete;
Value& operator=(Value&& other) noexcept = delete;
explicit Value(Type *ty, std::string name = "")
explicit Value(Type *ty, std::string name = "")
: type_(ty), name_(std::move(name)){}
virtual ~Value();
......
......@@ -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"
......
......@@ -108,7 +108,7 @@ Value* CminusfBuilder::visit(ASTVarDeclaration &node) {
}
Value* CminusfBuilder::visit(ASTFunDeclaration &node) {
Type *ret_type;
Type *ret_type;
std::vector<Type *> param_types;
if (node.type == TYPE_INT)
ret_type = INT32_T;
......@@ -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);
}
......@@ -2,14 +2,14 @@
std::string ptr_to_str(const void* ptr)
{
const char* translate = "0123456789abcdef";
const char* translate = "0123456789abcdef";
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
uintptr_t a = addr & 0xF;
uintptr_t b = (addr >> 4) & 0xF;
uintptr_t c = (addr >> 8) & 0xF;
uintptr_t d = (addr >> 12) & 0xF;
uintptr_t a = addr & 0xF;
uintptr_t b = (addr >> 4) & 0xF;
uintptr_t c = (addr >> 8) & 0xF;
uintptr_t d = (addr >> 12) & 0xF;
return {'<', translate[d], translate[c], translate[b], translate[a], '>'};
return {'<', translate[d], translate[c], translate[b], translate[a], '>'};
}
......@@ -47,7 +47,7 @@ void BasicBlock::add_instruction(Instruction *instr) {
auto it = instr_list_.begin();
for (; it != instr_list_.end() && ((*it)->is_alloca() || (*it)->is_phi()); ++it){}
instr_list_.emplace(it, instr);
return;
return;
}
assert(not is_terminated() && "Inserting instruction to terminated bb");
instr_list_.push_back(instr);
......@@ -56,7 +56,7 @@ void BasicBlock::add_instruction(Instruction *instr) {
void BasicBlock::add_instr_begin(Instruction* instr)
{
if (instr->is_alloca() || instr->is_phi())
instr_list_.push_front(instr);
instr_list_.push_front(instr);
else
{
auto it = instr_list_.begin();
......@@ -121,8 +121,8 @@ BasicBlock::~BasicBlock()
BasicBlock* BasicBlock::get_entry_block_of_same_function() const
{
assert(parent_ != nullptr && "bb have no parent function");
return parent_->get_entry_block();
assert(parent_ != nullptr && "bb have no parent function");
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
......@@ -168,7 +168,7 @@ std::string ConstantFP::print() {
ConstantZero *ConstantZero::get(Type *ty, Module *m) {
if (not cached_zero[ty])
{
cached_zero[ty] = std::unique_ptr<ConstantZero>(new ConstantZero(ty));
cached_zero[ty] = std::unique_ptr<ConstantZero>(new ConstantZero(ty));
}
return cached_zero[ty].get();
}
......
......@@ -3,31 +3,33 @@
#include "Module.hpp"
#include "Instruction.hpp"
#include <cassert>
#include <string>
#include <unordered_set>
#include <queue>
namespace
{
std::string chopName(std::string name)
{
if (name.size() > 4) return { name.begin(), name.begin() + 4 };
std::string chopName(std::string name)
{
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_);
}
......
......@@ -217,7 +217,7 @@ std::string Instruction::safe_print() const
switch (op_id_)
{
case ret:
{
{
std::string instr_ir;
instr_ir += get_instr_op_name();
instr_ir += " ";
......@@ -230,9 +230,9 @@ std::string Instruction::safe_print() const
instr_ir += "void";
}
return instr_ir;
}
}
case br:
{
{
std::string instr_ir;
instr_ir += safe_print_instr_op_name(get_instr_type());
instr_ir += " ";
......@@ -244,7 +244,7 @@ std::string Instruction::safe_print() const
instr_ir += safe_print_op_as_op(this, 2, true);
}
return instr_ir;
}
}
case add:
case sub:
case mul:
......@@ -265,7 +265,7 @@ std::string Instruction::safe_print() const
return instr_ir;
}
case alloca:
{
{
std::string instr_ir;
instr_ir += safe_print_as_op(this, true);
instr_ir += " = ";
......@@ -284,9 +284,9 @@ std::string Instruction::safe_print() const
else instr_ir += ty2->safe_print();
}
return instr_ir;
}
}
case load:
{
{
std::string instr_ir;
instr_ir += safe_print_as_op(this, true);
instr_ir += " = ";
......@@ -294,9 +294,9 @@ std::string Instruction::safe_print() const
instr_ir += " ";
instr_ir += safe_print_op_as_op(this, 0, true);
return instr_ir;
}
}
case store:
{
{
std::string instr_ir;
instr_ir += safe_print_instr_op_name(get_instr_type());
instr_ir += " ";
......@@ -304,7 +304,7 @@ std::string Instruction::safe_print() const
instr_ir += ", ";
instr_ir += safe_print_op_as_op(this, 1, true);
return instr_ir;
}
}
case ge:
case gt:
case le:
......@@ -340,8 +340,8 @@ std::string Instruction::safe_print() const
return instr_ir;
}
case phi:
{
std::string instr_ir;
{
std::string instr_ir;
instr_ir += safe_print_as_op(this, true);
instr_ir += " = ";
instr_ir += safe_print_instr_op_name(get_instr_type());
......@@ -356,7 +356,7 @@ std::string Instruction::safe_print() const
instr_ir += " ]";
}
return instr_ir;
}
}
case call:
{
std::string instr_ir;
......@@ -410,7 +410,7 @@ std::string Instruction::safe_print() const
return instr_ir;
}
case getelementptr:
{
{
std::string instr_ir;
instr_ir += safe_print_as_op(this, true);
instr_ir += " = ";
......@@ -422,11 +422,11 @@ std::string Instruction::safe_print() const
instr_ir += safe_print_op_as_op(this, i, true);
}
return instr_ir;
}
}
case zext:
case fptosi:
case sitofp:
{
{
std::string instr_ir;
instr_ir += safe_print_as_op(this, true);
instr_ir += " = ";
......@@ -434,7 +434,7 @@ std::string Instruction::safe_print() const
instr_ir += " ";
instr_ir += safe_print_op_as_op(this, 0, true);
return instr_ir;
}
}
}
std::string str;
str += safe_print_as_op(this, true);
......@@ -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";
}
......
......@@ -15,7 +15,7 @@ Instruction::Instruction(Type *ty, OpID id, const std::string& name, BasicBlock
assert(ty != nullptr && "Instruction have null type");
assert(((!ty->is_void_type()) || name.empty()) && "Void Type Instruction should not have name");
if (parent)
parent->add_instruction(this);
parent->add_instruction(this);
if (!ty->is_void_type() && parent && parent->get_parent())
set_name(parent_->get_parent()->names4insts_.get_name(name));
}
......@@ -226,7 +226,7 @@ GetElementPtrInst::GetElementPtrInst(Value *ptr, const std::vector<Value *>& idx
add_operand(ptr);
for (auto idx : idxs)
{
assert(idx->get_type()->is_integer_type() && "Index is not integer");
assert(idx->get_type()->is_integer_type() && "Index is not integer");
add_operand(idx);
}
}
......@@ -309,7 +309,7 @@ ZextInst::ZextInst(Value *val, Type *ty, BasicBlock *bb, const std::string& name
"ZextInst operand is not integer");
assert(ty->is_integer_type() && "ZextInst destination type is not integer");
assert((dynamic_cast<IntegerType *>(val->get_type())->get_num_bits() <
dynamic_cast<IntegerType *>(ty)->get_num_bits()) &&
dynamic_cast<IntegerType *>(ty)->get_num_bits()) &&
"ZextInst operand bit size is not smaller than destination type bit "
"size");
add_operand(val);
......@@ -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
......@@ -23,7 +23,7 @@ Module::~Module()
for (auto& i : pointer_map_) delete i.second;
for (auto& i : array_map_) delete i.second;
for (auto& i : function_map_) delete i.second;
for (auto i : function_list_) delete i;
for (auto i : function_list_) delete i;
for (auto i : global_list_) delete i;
}
......
......@@ -2,25 +2,31 @@
std::string Names::get_name(std::string name)
{
int ed = static_cast<int>(name.size());
while (ed > 0)
{
char ch = name[ed - 1];
if ((use_underline_ && ch == '_') || (ch >= '0' && ch <= '9')) ed--;
else break;
}
if (ed == 0) return get_name();
std::string name1 = {name.begin(), 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);
int ed = static_cast<int>(name.size());
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 (ch == '_' || (ch >= '0' && ch <= '9')) ed--;
else break;
}
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;
return get + std::to_string(idx);
}
std::string Names::get_name()
{
auto get = appended_prefix_ + default_prefix_;
return get + std::to_string(++default_prefix_used_count_);
auto get = appended_prefix_ + default_prefix_;
return get + std::to_string(++default_prefix_used_count_);
}
......@@ -72,11 +72,11 @@ std::string Type::print() const {
case IntegerTyID:
type_ir += "i";
type_ir += std::to_string(
dynamic_cast<const IntegerType *>(this)->get_num_bits());
dynamic_cast<const IntegerType *>(this)->get_num_bits());
break;
case FunctionTyID:
type_ir +=
dynamic_cast<const FunctionType *>(this)->get_return_type()->print();
dynamic_cast<const FunctionType *>(this)->get_return_type()->print();
type_ir += " (";
for (unsigned i = 0;
i < dynamic_cast<const FunctionType *>(this)->get_num_of_args();
......@@ -96,10 +96,10 @@ std::string Type::print() const {
case ArrayTyID:
type_ir += "[";
type_ir += std::to_string(
dynamic_cast<const ArrayType *>(this)->get_num_of_elements());
dynamic_cast<const ArrayType *>(this)->get_num_of_elements());
type_ir += " x ";
type_ir +=
dynamic_cast<const ArrayType *>(this)->get_element_type()->print();
dynamic_cast<const ArrayType *>(this)->get_element_type()->print();
type_ir += "]";
break;
case FloatTyID:
......@@ -119,38 +119,38 @@ std::string Type::safe_print() const
case LabelTyID:
return "label";
case IntegerTyID:
{
auto ty = dynamic_cast<const IntegerType*>(this);
{
auto ty = dynamic_cast<const IntegerType*>(this);
if (ty == nullptr) return "<not IntegerType>";
return "i" + std::to_string(ty->get_num_bits());
}
return "i" + std::to_string(ty->get_num_bits());
}
case FunctionTyID:
{
auto ty = dynamic_cast<const FunctionType*>(this);
if (ty == nullptr) return "<not FunctionType>";
{
auto ty = dynamic_cast<const FunctionType*>(this);
if (ty == nullptr) return "<not FunctionType>";
auto ty2 = ty->get_return_type();
std::string type_ir = (ty2 == nullptr ? "<null>" : ty2->safe_print()) + " (";
for (unsigned i = 0; i < ty->get_num_of_args(); i++) {
if (i) type_ir += ", ";
for (unsigned i = 0; i < ty->get_num_of_args(); i++) {
if (i) type_ir += ", ";
ty2 = ty->get_param_type(i);
type_ir += (ty2 == nullptr ? "<null>" : ty2->safe_print());
}
type_ir += (ty2 == nullptr ? "<null>" : ty2->safe_print());
}
return type_ir + ")";
}
}
case PointerTyID:
{
auto ty = dynamic_cast<const PointerType*>(this);
{
auto ty = dynamic_cast<const PointerType*>(this);
if (ty == nullptr) return "<not PointerType>";
auto ty2 = ty->get_element_type();
return (ty2 == nullptr ? "<null>" : ty2->safe_print()) + "*";
}
}
case ArrayTyID:
{
auto ty = dynamic_cast<const ArrayType*>(this);
{
auto ty = dynamic_cast<const ArrayType*>(this);
if (ty == nullptr) return "<not ArrayType>";
auto ty2 = ty->get_element_type();
return "[" + std::to_string(ty->get_num_of_elements()) + "x" + (ty2 == nullptr ? "<null>" : ty2->safe_print()) + "]";
}
}
case FloatTyID:
return "float";
}
......
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