Commit a0b2bd9d authored by 李晓奇's avatar 李晓奇

finish part1: hand write .ll file

parent 3b086a0e
...@@ -11,7 +11,8 @@ class ArrayType; ...@@ -11,7 +11,8 @@ class ArrayType;
class PointerType; class PointerType;
class FloatType; class FloatType;
class Type { class Type
{
public: public:
enum TypeID { enum TypeID {
VoidTyID, // Void VoidTyID, // Void
...@@ -77,7 +78,8 @@ class Type { ...@@ -77,7 +78,8 @@ class Type {
Module *m_; Module *m_;
}; };
class IntegerType : public Type { class IntegerType : public Type
{
public: public:
explicit IntegerType(unsigned num_bits, Module *m); explicit IntegerType(unsigned num_bits, Module *m);
...@@ -89,7 +91,8 @@ class IntegerType : public Type { ...@@ -89,7 +91,8 @@ class IntegerType : public Type {
unsigned num_bits_; unsigned num_bits_;
}; };
class FunctionType : public Type { class FunctionType : public Type
{
public: public:
FunctionType(Type *result, std::vector<Type *> params); FunctionType(Type *result, std::vector<Type *> params);
...@@ -110,7 +113,8 @@ class FunctionType : public Type { ...@@ -110,7 +113,8 @@ class FunctionType : public Type {
std::vector<Type *> args_; std::vector<Type *> args_;
}; };
class ArrayType : public Type { class ArrayType : public Type
{
public: public:
ArrayType(Type *contained, unsigned num_elements); ArrayType(Type *contained, unsigned num_elements);
...@@ -126,7 +130,8 @@ class ArrayType : public Type { ...@@ -126,7 +130,8 @@ class ArrayType : public Type {
unsigned num_elements_; // Number of elements in the array. unsigned num_elements_; // Number of elements in the array.
}; };
class PointerType : public Type { class PointerType : public Type
{
public: public:
PointerType(Type *contained); PointerType(Type *contained);
Type *get_element_type() const { return contained_; } Type *get_element_type() const { return contained_; }
...@@ -137,7 +142,8 @@ class PointerType : public Type { ...@@ -137,7 +142,8 @@ class PointerType : public Type {
Type *contained_; // The element type of the ptr. Type *contained_; // The element type of the ptr.
}; };
class FloatType : public Type { class FloatType : public Type
{
public: public:
FloatType(Module *m); FloatType(Module *m);
static FloatType *get(Module *m); static FloatType *get(Module *m);
......
define dso_local i32 @main() #0 {
%a = alloca [10 x i32], align 4
; 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
%a1 = getelementptr i32, i32* %ptr, i64 1
store i32 10, i32* %a0
%v1 = load i32, i32* %a0
%v2 = mul i32 %v1, 2
store i32 %v2, i32* %a1
%r = load i32, i32* %a1
ret i32 %r
}
define dso_local i32 @callee(i32 %0) #0 {
%r = mul i32 %0, 2
ret i32 %r
}
define dso_local i32 @main() #0 {
%r = call i32 @callee(i32 110)
ret i32 %r
}
define i32 @main(){
%a_ptr = alloca float
store float 0x40163851E0000000, float* %a_ptr
%a = load float, float* %a_ptr
%cond = fcmp ugt float %a, 1.000000e+00
br i1 %cond, label %1, label %2
1:
ret i32 233
2:
ret i32 0
}
define dso_local i32 @main() #0 {
%pa = alloca i32
%pi = alloca i32
store i32 10, i32* %pa
store i32 0, i32* %pi
br label %loop_head
loop_head:
%i = load i32, i32* %pi
%cond = icmp slt i32 %i, 10
br i1 %cond, label %loop_body, label %over
loop_body:
%i_1 = add i32 %i, 1
store i32 %i_1, i32* %pi
%newi = load i32, i32* %pi
%a = load i32, i32* %pa
%a_i = add i32 %a, %newi
store i32 %a_i, i32* %pa
br label %loop_head
over:
%r = load i32, i32* %pa
ret i32 %r
}
...@@ -8,44 +8,48 @@ ...@@ -8,44 +8,48 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#ifdef DEBUG // 用于调试信息,大家可以在编译过程中通过" -DDEBUG"来开启这一选项 /* #ifdef DEBUG // 用于调试信息,大家可以在编译过程中通过" -DDEBUG"来开启这一选项
* #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; // 输出行号的简单示例
#else
#define DEBUG_OUTPUT
#endif
#define CONST_INT(num) ConstantInt::get(num, module) #define CONST_INT(num) ConstantInt::get(num, mod)
#define CONST_FP(num) ConstantFP::get(num, module) // 得到常数值的表示,方便后面多次用到 #define CONST_FP(num) \
ConstantFP::get(num, mod) // 得到常数值的表示,方便后面多次用到
int main() { int main()
auto module = new Module("Cminus code"); // module name是什么无关紧要 {
auto builder = new IRBuilder(nullptr, module); auto mod = new Module("Cminus code"); // module name是什么无关紧要
Type *Int32Type = Type::get_int32_type(module); auto builder = new IRBuilder(nullptr, mod);
Type *Int32Type = Type::get_int32_type(mod);
// 全局数组,x,y // 全局数组,x,y
auto *arrayType = ArrayType::get(Int32Type, 1); auto *arrayType = ArrayType::get(Int32Type, 1);
auto initializer = ConstantZero::get(Int32Type, module); auto initializer = ConstantZero::get(Int32Type, mod);
auto x = GlobalVariable::create("x", module, arrayType, false, initializer);// 参数解释: 名字name,所属module,全局变量类型type, // 参数解释: 名字name,所属module,全局变量类型type,
auto y = GlobalVariable::create("y", module, arrayType, false, initializer);// 是否是常量定义(cminus中没有常量概念,应全都是false),初始化常量(ConstantZero类) auto x = GlobalVariable::create("x", mod, arrayType, false, initializer);
// 是否是常量定义(cminus中没有常量概念,应全都是false),初始化常量(ConstantZero类)
auto y = GlobalVariable::create("y", mod, arrayType, false, initializer);
// gcd函数 // gcd函数
// 函数参数类型的vector // 函数参数类型的vector
std::vector<Type *> Ints(2, Int32Type); std::vector<Type *> Ints(2, Int32Type);
//通过返回值类型与参数类型列表得到函数类型 // 通过返回值类型与参数类型列表得到函数类型
auto gcdFunTy = FunctionType::get(Int32Type, Ints); auto gcdFunTy = FunctionType::get(Int32Type, Ints);
// 由函数类型得到函数 // 由函数类型得到函数
auto gcdFun = Function::create(gcdFunTy, auto gcdFun = Function::create(gcdFunTy, "gcd", mod);
"gcd", module);
// BB的名字在生成中无所谓,但是可以方便阅读 // BB的名字在生成中无所谓,但是可以方便阅读
auto bb = BasicBlock::create(module, "entry", gcdFun); auto bb = BasicBlock::create(mod, "entry", gcdFun);
builder->set_insert_point(bb); // 一个BB的开始,将当前插入指令点的位置设在bb builder->set_insert_point(bb); // 一个BB的开始,将当前插入指令点的位置设在bb
auto retAlloca = builder->create_alloca(Int32Type); // 在内存中分配返回值的位置 auto retAlloca =
builder->create_alloca(Int32Type); // 在内存中分配返回值的位置
auto uAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数u的位置 auto uAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数u的位置
auto vAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数v的位置 auto vAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数v的位置
...@@ -58,16 +62,18 @@ int main() { ...@@ -58,16 +62,18 @@ int main() {
builder->create_store(args[1], vAlloca); // 将参数v store下来 builder->create_store(args[1], vAlloca); // 将参数v store下来
auto vLoad = builder->create_load(vAlloca); // 将参数v load上来 auto vLoad = builder->create_load(vAlloca); // 将参数v load上来
auto icmp = builder->create_icmp_eq(vLoad, CONST_INT(0)); // v和0的比较,注意ICMPEQ auto icmp =
builder->create_icmp_eq(vLoad, CONST_INT(0)); // v和0的比较,注意ICMPEQ
auto trueBB = BasicBlock::create(module, "trueBB", gcdFun); // true分支 auto trueBB = BasicBlock::create(mod, "trueBB", gcdFun); // true分支
auto falseBB = BasicBlock::create(module, "falseBB", gcdFun); // false分支 auto falseBB = BasicBlock::create(mod, "falseBB", gcdFun); // false分支
auto retBB = BasicBlock::create( auto retBB = BasicBlock::create(
module, "", gcdFun); // return分支,提前create,以便true分支可以br mod, "", gcdFun); // return分支,提前create,以便true分支可以br
auto br = builder->create_cond_br(icmp, trueBB, falseBB); // 条件BR auto br = builder->create_cond_br(icmp, trueBB, falseBB); // 条件BR
DEBUG_OUTPUT // 调试的时候故意留下来的,以醒目地提醒你这个调试用的宏定义方法 DEBUG_OUTPUT // 调试的时候故意留下来的,以醒目地提醒你这个调试用的宏定义方法
builder->set_insert_point(trueBB); // if true; 分支的开始需要SetInsertPoint设置 builder->set_insert_point(
trueBB); // if true; 分支的开始需要SetInsertPoint设置
auto uLoad = builder->create_load(uAlloca); auto uLoad = builder->create_load(uAlloca);
builder->create_store(uLoad, retAlloca); builder->create_store(uLoad, retAlloca);
builder->create_br(retBB); // br retBB builder->create_br(retBB); // br retBB
...@@ -88,11 +94,11 @@ int main() { ...@@ -88,11 +94,11 @@ int main() {
builder->create_ret(retLoad); builder->create_ret(retLoad);
// funArray函数 // funArray函数
auto Int32PtrType = Type::get_int32_ptr_type(module); // 单个参数的类型,指针 auto Int32PtrType = Type::get_int32_ptr_type(mod); // 单个参数的类型,指针
std::vector<Type *> IntPtrs(2, Int32PtrType); // 参数列表类型 std::vector<Type *> IntPtrs(2, Int32PtrType); // 参数列表类型
auto funArrayFunType = FunctionType::get(Int32Type, IntPtrs); // 函数类型 auto funArrayFunType = FunctionType::get(Int32Type, IntPtrs); // 函数类型
auto funArrayFun = Function::create(funArrayFunType, "funArray", module); auto funArrayFun = Function::create(funArrayFunType, "funArray", mod);
bb = BasicBlock::create(module, "entry", funArrayFun); bb = BasicBlock::create(mod, "entry", funArrayFun);
builder->set_insert_point(bb); builder->set_insert_point(bb);
auto upAlloca = builder->create_alloca(Int32PtrType); // u的存放 auto upAlloca = builder->create_alloca(Int32PtrType); // u的存放
auto vpAlloca = builder->create_alloca(Int32PtrType); // v的存放 auto vpAlloca = builder->create_alloca(Int32PtrType); // v的存放
...@@ -100,15 +106,18 @@ int main() { ...@@ -100,15 +106,18 @@ int main() {
auto bAlloca = builder->create_alloca(Int32Type); // b的存放 auto bAlloca = builder->create_alloca(Int32Type); // b的存放
auto tempAlloca = builder->create_alloca(Int32Type); // temp的存放 auto tempAlloca = builder->create_alloca(Int32Type); // temp的存放
std::vector<Value *> args1; //获取funArrayFun函数的形参,通过Function中的iterator std::vector<Value *>
for (auto arg = funArrayFun->arg_begin(); arg != funArrayFun->arg_end(); arg++) { args1; //获取funArrayFun函数的形参,通过Function中的iterator
for (auto arg = funArrayFun->arg_begin(); arg != funArrayFun->arg_end();
arg++) {
args1.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素 args1.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
} }
builder->create_store(args1[0], upAlloca); // 将参数u store下来 builder->create_store(args1[0], upAlloca); // 将参数u store下来
builder->create_store(args1[1], vpAlloca); // 将参数v store下来 builder->create_store(args1[1], vpAlloca); // 将参数v store下来
auto u0pLoad = builder->create_load(upAlloca); // 读取u auto u0pLoad = builder->create_load(upAlloca); // 读取u
auto u0GEP = builder->create_gep(u0pLoad, {CONST_INT(0)}); // GEP: 获取u[0]地址 auto u0GEP =
builder->create_gep(u0pLoad, {CONST_INT(0)}); // GEP: 获取u[0]地址
auto u0Load = builder->create_load(u0GEP); // 从u[0]地址 读取u[0] auto u0Load = builder->create_load(u0GEP); // 从u[0]地址 读取u[0]
builder->create_store(u0Load, aAlloca); // 将u[0] 写入 a builder->create_store(u0Load, aAlloca); // 将u[0] 写入 a
auto v0pLoad = builder->create_load(vpAlloca); // 同上 auto v0pLoad = builder->create_load(vpAlloca); // 同上
...@@ -119,8 +128,8 @@ int main() { ...@@ -119,8 +128,8 @@ int main() {
auto aLoad = builder->create_load(aAlloca); auto aLoad = builder->create_load(aAlloca);
auto bLoad = builder->create_load(bAlloca); auto bLoad = builder->create_load(bAlloca);
icmp = builder->create_icmp_lt(aLoad, bLoad); icmp = builder->create_icmp_lt(aLoad, bLoad);
trueBB = BasicBlock::create(module, "trueBB", funArrayFun); trueBB = BasicBlock::create(mod, "trueBB", funArrayFun);
falseBB = BasicBlock::create(module, "falseBB", funArrayFun); falseBB = BasicBlock::create(mod, "falseBB", funArrayFun);
builder->create_cond_br(icmp, trueBB, falseBB); builder->create_cond_br(icmp, trueBB, falseBB);
builder->set_insert_point(trueBB); builder->set_insert_point(trueBB);
...@@ -136,25 +145,29 @@ int main() { ...@@ -136,25 +145,29 @@ int main() {
call = builder->create_call(gcdFun, {aLoad, bLoad}); call = builder->create_call(gcdFun, {aLoad, bLoad});
builder->create_ret(call); builder->create_ret(call);
// main函数 // main函数
auto mainFun = Function::create(FunctionType::get(Int32Type, {}), auto mainFun =
"main", module); Function::create(FunctionType::get(Int32Type, {}), "main", mod);
bb = BasicBlock::create(module, "entry", mainFun); bb = BasicBlock::create(mod, "entry", mainFun);
// BasicBlock的名字在生成中无所谓,但是可以方便阅读 // BasicBlock的名字在生成中无所谓,但是可以方便阅读
builder->set_insert_point(bb); builder->set_insert_point(bb);
retAlloca = builder->create_alloca(Int32Type); retAlloca = builder->create_alloca(Int32Type);
builder->create_store(CONST_INT(0), retAlloca); // 默认 ret 0 builder->create_store(CONST_INT(0), retAlloca); // 默认 ret 0
//
auto x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)}); // GEP: 这里为什么是{0, 0}呢? (实验报告相关) // GEP: 这里为什么是{0, 0}呢? (实验报告相关)
auto x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)});
builder->create_store(CONST_INT(90), x0GEP); builder->create_store(CONST_INT(90), x0GEP);
auto y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)}); // GEP: 这里为什么是{0, 0}呢? (实验报告相关) //
// GEP: 这里为什么是{0, 0}呢? (实验报告相关)
auto y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)});
builder->create_store(CONST_INT(18), y0GEP); builder->create_store(CONST_INT(18), y0GEP);
x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)}); x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)});
y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)}); y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)});
call = builder->create_call(funArrayFun, {x0GEP, y0GEP}); // 为什么这里传的是{x0GEP, y0GEP}呢? //
// 为什么这里传的是{x0GEP, y0GEP}呢?
call = builder->create_call(funArrayFun, {x0GEP, y0GEP});
builder->create_ret(call); builder->create_ret(call);
// 尽管已经有很多注释,但可能还是会遇到很多bug // 尽管已经有很多注释,但可能还是会遇到很多bug
...@@ -164,7 +177,7 @@ int main() { ...@@ -164,7 +177,7 @@ int main() {
// 对于额外的指令,包括数组,在之后的实验中可能需要大家自己搜索一下思考一下, // 对于额外的指令,包括数组,在之后的实验中可能需要大家自己搜索一下思考一下,
// 还有涉及到的C++语法,可以及时提问或者向大家提供指导哦! // 还有涉及到的C++语法,可以及时提问或者向大家提供指导哦!
// 对于这个例子里的代码风格/用法,如果有好的建议也欢迎提出! // 对于这个例子里的代码风格/用法,如果有好的建议也欢迎提出!
std::cout << module->print(); std::cout << mod->print();
delete module; delete mod;
return 0; return 0;
} }
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