Commit 4b7accb1 authored by 李晓奇's avatar 李晓奇

finish part2: write cpp to generate .ll file

parent a0b2bd9d
......@@ -2,5 +2,6 @@ build
Documentations/1-parser/*.pdf
compile_commands.json
.cache
todo.txt
tmp.cminus
......@@ -18,11 +18,13 @@ class Argument;
class Type;
class FunctionType;
class Function : public Value, public llvm::ilist_node<Function> {
class Function : public Value, public llvm::ilist_node<Function>
{
public:
Function(FunctionType *ty, const std::string &name, Module *parent);
virtual ~Function();
static Function *create(FunctionType *ty, const std::string &name, Module *parent);
static Function *create(FunctionType *ty, const std::string &name,
Module *parent);
FunctionType *get_function_type() const;
......@@ -38,15 +40,15 @@ class Function : public Value, public llvm::ilist_node<Function> {
std::list<Argument *>::iterator arg_begin() { return arguments_.begin(); }
std::list<Argument *>::iterator arg_end() { return arguments_.end(); }
void remove(BasicBlock *bb);
void remove(BasicBlock *bb);
BasicBlock *get_entry_block() { return &*basic_blocks_.begin(); }
llvm::ilist<BasicBlock> &get_basic_blocks() { return basic_blocks_; }
std::list<Argument *> &get_args() { return arguments_; }
std::list<Argument *> &get_args() { return arguments_; }
bool is_declaration() { return basic_blocks_.empty(); }
void set_instr_name();
void set_instr_name();
std::string print();
private:
......@@ -54,27 +56,33 @@ class Function : public Value, public llvm::ilist_node<Function> {
private:
llvm::ilist<BasicBlock> basic_blocks_; // basic blocks
std::list<Argument *> arguments_; // arguments
Module *parent_;
unsigned seq_cnt_;
std::list<Argument *> arguments_; // arguments
Module *parent_;
unsigned seq_cnt_;
// unsigned num_args_;
// We don't need this, all value inside function should be unnamed
// std::map<std::string, Value*> sym_table_; // Symbol table of args/instructions
// std::map<std::string, Value*> sym_table_; // Symbol table of
// args/instructions
};
// Argument of Function, does not contain actual value
class Argument : public Value {
class Argument : public Value
{
public:
/// Argument constructor.
explicit Argument(Type *ty, const std::string &name = "", Function *f = nullptr, unsigned arg_no = 0)
: Value(ty, name), parent_(f), arg_no_(arg_no) {}
explicit Argument(Type *ty, const std::string &name = "",
Function *f = nullptr, unsigned arg_no = 0)
: Value(ty, name), parent_(f), arg_no_(arg_no)
{
}
virtual ~Argument() {}
inline const Function *get_parent() const { return parent_; }
inline Function *get_parent() { return parent_; }
inline 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 {
unsigned get_arg_no() const
{
assert(parent_ && "can't get number of unparented arg");
return arg_no_;
}
......@@ -83,7 +91,7 @@ class Argument : public Value {
private:
Function *parent_;
unsigned arg_no_; // argument No.
unsigned arg_no_; // argument No.
};
#endif // SYSYC_FUNCTION_H
......@@ -6,96 +6,169 @@
#include "Instruction.h"
#include "Value.h"
class IRBuilder {
class IRBuilder
{
private:
BasicBlock *BB_;
Module *m_;
Module *m_;
public:
IRBuilder(BasicBlock *bb, Module *m) : BB_(bb), m_(m){};
~IRBuilder() = default;
Module *get_module() { return m_; }
Module *get_module() { return m_; }
BasicBlock *get_insert_block() { return this->BB_; }
void set_insert_point(BasicBlock *bb) { this->BB_ = bb; } // 在某个基本块中插入指令
BinaryInst *create_iadd(Value *lhs, Value *rhs) {
void set_insert_point(BasicBlock *bb)
{
this->BB_ = bb;
} // 在某个基本块中插入指令
BinaryInst *create_iadd(Value *lhs, Value *rhs)
{
return BinaryInst::create_add(lhs, rhs, this->BB_, m_);
} // 创建加法指令(以及其他算术指令)
BinaryInst *create_isub(Value *lhs, Value *rhs) { return BinaryInst::create_sub(lhs, rhs, this->BB_, m_); }
BinaryInst *create_imul(Value *lhs, Value *rhs) { return BinaryInst::create_mul(lhs, rhs, this->BB_, m_); }
BinaryInst *create_isdiv(Value *lhs, Value *rhs) { return BinaryInst::create_sdiv(lhs, rhs, this->BB_, m_); }
BinaryInst *create_isub(Value *lhs, Value *rhs)
{
return BinaryInst::create_sub(lhs, rhs, this->BB_, m_);
}
BinaryInst *create_imul(Value *lhs, Value *rhs)
{
return BinaryInst::create_mul(lhs, rhs, this->BB_, m_);
}
BinaryInst *create_isdiv(Value *lhs, Value *rhs)
{
return BinaryInst::create_sdiv(lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_eq(Value *lhs, Value *rhs) {
CmpInst *create_icmp_eq(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::EQ, lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_ne(Value *lhs, Value *rhs) {
CmpInst *create_icmp_ne(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::NE, lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_gt(Value *lhs, Value *rhs) {
CmpInst *create_icmp_gt(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::GT, lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_ge(Value *lhs, Value *rhs) {
CmpInst *create_icmp_ge(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::GE, lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_lt(Value *lhs, Value *rhs) {
CmpInst *create_icmp_lt(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::LT, lhs, rhs, this->BB_, m_);
}
CmpInst *create_icmp_le(Value *lhs, Value *rhs) {
CmpInst *create_icmp_le(Value *lhs, Value *rhs)
{
return CmpInst::create_cmp(CmpInst::LE, lhs, rhs, this->BB_, m_);
}
CallInst *create_call(Value *func, std::vector<Value *> args) {
assert(dynamic_cast<Function *>(func) && "func must be Function * type");
CallInst *create_call(Value *func, std::vector<Value *> args)
{
assert(dynamic_cast<Function *>(func) &&
"func must be Function * type");
return CallInst::create(static_cast<Function *>(func), args, this->BB_);
}
BranchInst *create_br(BasicBlock *if_true) { return BranchInst::create_br(if_true, this->BB_); }
BranchInst *create_cond_br(Value *cond, BasicBlock *if_true, BasicBlock *if_false) {
BranchInst *create_br(BasicBlock *if_true)
{
return BranchInst::create_br(if_true, this->BB_);
}
BranchInst *create_cond_br(Value *cond, BasicBlock *if_true,
BasicBlock *if_false)
{
return BranchInst::create_cond_br(cond, if_true, if_false, this->BB_);
}
ReturnInst *create_ret(Value *val) { return ReturnInst::create_ret(val, this->BB_); }
ReturnInst *create_void_ret() { return ReturnInst::create_void_ret(this->BB_); }
ReturnInst *create_ret(Value *val)
{
return ReturnInst::create_ret(val, this->BB_);
}
ReturnInst *create_void_ret()
{
return ReturnInst::create_void_ret(this->BB_);
}
GetElementPtrInst *create_gep(Value *ptr, std::vector<Value *> idxs) {
GetElementPtrInst *create_gep(Value *ptr, std::vector<Value *> idxs)
{
return GetElementPtrInst::create_gep(ptr, idxs, this->BB_);
}
StoreInst *create_store(Value *val, Value *ptr) { return StoreInst::create_store(val, ptr, this->BB_); }
LoadInst *create_load(Type *ty, Value *ptr) { return LoadInst::create_load(ty, ptr, this->BB_); }
LoadInst *create_load(Value *ptr) {
assert(ptr->get_type()->is_pointer_type() && "ptr must be pointer type");
return LoadInst::create_load(ptr->get_type()->get_pointer_element_type(), ptr, this->BB_);
StoreInst *create_store(Value *val, Value *ptr)
{
return StoreInst::create_store(val, ptr, this->BB_);
}
LoadInst *create_load(Type *ty, Value *ptr)
{
return LoadInst::create_load(ty, ptr, this->BB_);
}
LoadInst *create_load(Value *ptr)
{
assert(ptr->get_type()->is_pointer_type() &&
"ptr must be pointer type");
return LoadInst::create_load(
ptr->get_type()->get_pointer_element_type(), ptr, this->BB_);
}
AllocaInst *create_alloca(Type *ty) { return AllocaInst::create_alloca(ty, this->BB_); }
ZextInst *create_zext(Value *val, Type *ty) { return ZextInst::create_zext(val, ty, this->BB_); }
AllocaInst *create_alloca(Type *ty)
{
return AllocaInst::create_alloca(ty, this->BB_);
}
ZextInst *create_zext(Value *val, Type *ty)
{
return ZextInst::create_zext(val, ty, this->BB_);
}
SiToFpInst *create_sitofp(Value *val, Type *ty) { return SiToFpInst::create_sitofp(val, ty, this->BB_); }
FpToSiInst *create_fptosi(Value *val, Type *ty) { return FpToSiInst::create_fptosi(val, ty, this->BB_); }
SiToFpInst *create_sitofp(Value *val, Type *ty)
{
return SiToFpInst::create_sitofp(val, ty, this->BB_);
}
FpToSiInst *create_fptosi(Value *val, Type *ty)
{
return FpToSiInst::create_fptosi(val, ty, this->BB_);
}
FCmpInst *create_fcmp_ne(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_ne(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::NE, lhs, rhs, this->BB_, m_);
}
FCmpInst *create_fcmp_lt(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_lt(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::LT, lhs, rhs, this->BB_, m_);
}
FCmpInst *create_fcmp_le(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_le(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::LE, lhs, rhs, this->BB_, m_);
}
FCmpInst *create_fcmp_ge(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_ge(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::GE, lhs, rhs, this->BB_, m_);
}
FCmpInst *create_fcmp_gt(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_gt(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::GT, lhs, rhs, this->BB_, m_);
}
FCmpInst *create_fcmp_eq(Value *lhs, Value *rhs) {
FCmpInst *create_fcmp_eq(Value *lhs, Value *rhs)
{
return FCmpInst::create_fcmp(FCmpInst::EQ, lhs, rhs, this->BB_, m_);
}
BinaryInst *create_fadd(Value *lhs, Value *rhs) { return BinaryInst::create_fadd(lhs, rhs, this->BB_, m_); }
BinaryInst *create_fsub(Value *lhs, Value *rhs) { return BinaryInst::create_fsub(lhs, rhs, this->BB_, m_); }
BinaryInst *create_fmul(Value *lhs, Value *rhs) { return BinaryInst::create_fmul(lhs, rhs, this->BB_, m_); }
BinaryInst *create_fdiv(Value *lhs, Value *rhs) { return BinaryInst::create_fdiv(lhs, rhs, this->BB_, m_); }
BinaryInst *create_fadd(Value *lhs, Value *rhs)
{
return BinaryInst::create_fadd(lhs, rhs, this->BB_, m_);
}
BinaryInst *create_fsub(Value *lhs, Value *rhs)
{
return BinaryInst::create_fsub(lhs, rhs, this->BB_, m_);
}
BinaryInst *create_fmul(Value *lhs, Value *rhs)
{
return BinaryInst::create_fmul(lhs, rhs, this->BB_, m_);
}
BinaryInst *create_fdiv(Value *lhs, Value *rhs)
{
return BinaryInst::create_fdiv(lhs, rhs, this->BB_, m_);
}
};
#endif // SYSYC_IRBUILDER_H
This diff is collapsed.
......@@ -8,35 +8,35 @@ target_link_libraries(
IR_lib
)
# add_executable(
# stu_assign_generator
# stu_cpp/assign_generator.cpp
# )
# target_link_libraries(
# stu_assign_generator
# IR_lib
# )
# add_executable(
# stu_fun_generator
# stu_cpp/fun_generator.cpp
# )
# target_link_libraries(
# stu_fun_generator
# IR_lib
# )
# add_executable(
# stu_if_generator
# stu_cpp/if_generator.cpp
# )
# target_link_libraries(
# stu_if_generator
# IR_lib
# )
# add_executable(
# stu_while_generator
# stu_cpp/while_generator.cpp
# )
# target_link_libraries(
# stu_while_generator
# IR_lib
# )
add_executable(
stu_assign_generator
stu_cpp/assign_generator.cpp
)
target_link_libraries(
stu_assign_generator
IR_lib
)
add_executable(
stu_fun_generator
stu_cpp/fun_generator.cpp
)
target_link_libraries(
stu_fun_generator
IR_lib
)
add_executable(
stu_if_generator
stu_cpp/if_generator.cpp
)
target_link_libraries(
stu_if_generator
IR_lib
)
add_executable(
stu_while_generator
stu_cpp/while_generator.cpp
)
target_link_libraries(
stu_while_generator
IR_lib
)
#include "Module.h"
#include "IRBuilder.h"
#include "Type.h"
#include "Constant.h"
#include <iostream>
#include <vector>
int main()
{
auto mod = new Module("assign.c");
auto bud = new IRBuilder(nullptr, mod);
auto I32Type = Type::get_int32_type(mod);
auto I32x10Type = Type::get_array_type(I32Type, 10);
std::vector<Type *> NoneArg;
auto mainTp = FunctionType::get(I32Type, NoneArg);
auto mainFunc = Function::create(mainTp, "main", mod);
auto bb = BasicBlock::create(mod, "entry", mainFunc);
bud->set_insert_point(bb);
auto arr_ptr = bud->create_alloca(I32x10Type);
auto a0_ptr = bud->create_gep(
arr_ptr, {ConstantInt::get(0, mod), ConstantInt::get(0, mod)});
auto a1_ptr = bud->create_gep(
arr_ptr, {ConstantInt::get(0, mod), ConstantInt::get(0, mod)});
bud->create_store(ConstantInt::get(10, mod), a0_ptr);
auto a0_load = bud->create_load(a0_ptr);
auto mul = bud->create_imul(a0_load, ConstantInt::get(2, mod));
bud->create_store(mul, a1_ptr);
auto a1_load = bud->create_load(a1_ptr);
bud->create_ret(a1_load);
std::cout << mod->print();
delete mod;
return 0;
}
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Module.h"
#include "Type.h"
#include <iostream>
int main()
{
auto mod = new Module("Cminus code"); // module name是什么无关紧要
auto bud = new IRBuilder(nullptr, mod);
Type *I32Type = Type::get_int32_type(mod);
std::vector<Type *> OneIntArg(1, I32Type);
auto calleeTp = FunctionType::get(I32Type, OneIntArg);
auto calleeFunc = Function::create(calleeTp, "callee", mod);
auto bb = BasicBlock::create(mod, "entry", calleeFunc);
bud->set_insert_point(bb);
std::vector<Value *> arg_vs;
for (auto arg = calleeFunc->arg_begin(); arg != calleeFunc->arg_end();
arg++)
arg_vs.push_back(*arg);
auto mul = bud->create_imul(arg_vs[0], ConstantInt::get(2, mod));
bud->create_ret(mul);
auto mainTp = FunctionType::get(I32Type, {});
auto mainFunc = Function::create(mainTp, "main", mod);
bb = BasicBlock::create(mod, "entry", mainFunc);
bud->set_insert_point(bb);
auto call = bud->create_call(calleeFunc, {ConstantInt::get(110, mod)});
bud->create_ret(call);
std::cout << mod->print();
delete mod;
return 0;
}
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Module.h"
#include "Type.h"
#include <iostream>
int main()
{
auto mod = new Module("if.c");
auto bud = new IRBuilder(nullptr, mod);
Type *I32Type = Type::get_int32_type(mod);
Type *floatType = Type::get_float_type(mod);
auto mainTp = FunctionType::get(I32Type, {});
auto mainFunc = Function::create(mainTp, "main", mod);
auto bb = BasicBlock::create(mod, "entry", mainFunc);
bud->set_insert_point(bb);
auto aAlloc = bud->create_alloca(floatType);
bud->create_store(ConstantFP::get(5.555, mod), aAlloc);
auto aValue = bud->create_load(aAlloc);
auto cond = bud->create_fcmp_gt(aValue, ConstantFP::get(1, mod));
auto TBB = BasicBlock::create(mod, "trueCase", mainFunc);
auto FBB = BasicBlock::create(mod, "falseCase", mainFunc);
bud->create_cond_br(cond, TBB, FBB);
bud->set_insert_point(TBB);
bud->create_ret(ConstantInt::get(233, mod));
bud->set_insert_point(FBB);
bud->create_ret(ConstantInt::get(0, mod));
std::cout << mod->print();
delete mod;
return 0;
}
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Module.h"
#include "Type.h"
#include <iostream>
int main()
{
auto mod = new Module("while.c");
auto bud = new IRBuilder(nullptr, mod);
Type *I32Type = Type::get_int32_type(mod);
// main函数
auto mainFunc =
Function::create(FunctionType::get(I32Type, {}), "main", mod);
auto bb = BasicBlock::create(mod, "entry", mainFunc);
auto judge = BasicBlock::create(mod, "judge", mainFunc);
auto loop = BasicBlock::create(mod, "loop", mainFunc);
auto exit = BasicBlock::create(mod, "exit", mainFunc);
bud->set_insert_point(bb);
auto aAlloc = bud->create_alloca(I32Type);
auto iAlloc = bud->create_alloca(I32Type);
bud->create_store(ConstantInt::get(10, mod), aAlloc);
bud->create_store(ConstantInt::get(0, mod), iAlloc);
bud->create_br(judge);
bud->set_insert_point(judge);
auto iV = bud->create_load(iAlloc);
auto cond = bud->create_icmp_lt(iV, ConstantInt::get(10, mod));
bud->create_cond_br(cond, loop, exit);
bud->set_insert_point(loop);
auto add = bud->create_iadd(iV, ConstantInt::get(1, mod));
bud->create_store(add, iAlloc);
//
auto aV = bud->create_load(aAlloc);
auto aadd = bud->create_iadd(add, aV);
bud->create_store(aadd, aAlloc);
bud->create_br(judge);
bud->set_insert_point(exit);
aV = bud->create_load(aAlloc);
bud->create_ret(aV);
std::cout << mod->print();
delete mod;
return 0;
}
define dso_local i32 @main() #0 {
%a = alloca [10 x i32], align 4
%a = alloca [10 x i32]
; ptr is the pointer with type i32*
%ptr = getelementptr [10 x i32], [10 x i32]* %a, i64 0, i64 0
%a0 = getelementptr i32, i32* %ptr, i64 0
; %a0 = getelementptr i32, i32* %ptr, i64 0
%a1 = getelementptr i32, i32* %ptr, i64 1
store i32 10, i32* %a0
%v1 = load i32, i32* %a0
store i32 10, i32* %ptr
%v1 = load i32, i32* %ptr
%v2 = mul i32 %v1, 2
store i32 %v2, i32* %a1
%r = load i32, i32* %a1
......
......@@ -12,12 +12,13 @@
* #define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; //
* 输出行号的简单示例 #else #define DEBUG_OUTPUT #endif */
#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; // 输出行号的简单示例
// 输出行号的简单示例
#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl;
#define CONST_INT(num) ConstantInt::get(num, mod)
#define CONST_FP(num) \
ConstantFP::get(num, mod) // 得到常数值的表示,方便后面多次用到
// 得到常数值的表示,方便后面多次用到
#define CONST_FP(num) ConstantFP::get(num, mod)
int main()
{
......@@ -71,9 +72,10 @@ int main()
mod, "", gcdFun); // return分支,提前create,以便true分支可以br
auto br = builder->create_cond_br(icmp, trueBB, falseBB); // 条件BR
DEBUG_OUTPUT // 调试的时候故意留下来的,以醒目地提醒你这个调试用的宏定义方法
builder->set_insert_point(
trueBB); // if true; 分支的开始需要SetInsertPoint设置
DEBUG_OUTPUT; // 调试的时候故意留下来的,以醒目地提醒你这个调试用的宏定义方法
// if true; 分支的开始需要SetInsertPoint设置
builder->set_insert_point(trueBB);
auto uLoad = builder->create_load(uAlloca);
builder->create_store(uLoad, retAlloca);
builder->create_br(retBB); // br retBB
......@@ -106,8 +108,8 @@ int main()
auto bAlloca = builder->create_alloca(Int32Type); // b的存放
auto tempAlloca = builder->create_alloca(Int32Type); // temp的存放
std::vector<Value *>
args1; //获取funArrayFun函数的形参,通过Function中的iterator
//获取funArray函数的形参,通过Function中的iterator
std::vector<Value *> args1;
for (auto arg = funArrayFun->arg_begin(); arg != funArrayFun->arg_end();
arg++) {
args1.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
......
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