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

finish part1: hand write .ll file

parent 3b086a0e
......@@ -11,7 +11,8 @@ class ArrayType;
class PointerType;
class FloatType;
class Type {
class Type
{
public:
enum TypeID {
VoidTyID, // Void
......@@ -73,11 +74,12 @@ class Type {
std::string print();
private:
TypeID tid_;
TypeID tid_;
Module *m_;
};
class IntegerType : public Type {
class IntegerType : public Type
{
public:
explicit IntegerType(unsigned num_bits, Module *m);
......@@ -89,7 +91,8 @@ class IntegerType : public Type {
unsigned num_bits_;
};
class FunctionType : public Type {
class FunctionType : public Type
{
public:
FunctionType(Type *result, std::vector<Type *> params);
......@@ -100,17 +103,18 @@ class FunctionType : public Type {
unsigned get_num_of_args() const;
Type *get_param_type(unsigned i) const;
Type *get_param_type(unsigned i) const;
std::vector<Type *>::iterator param_begin() { return args_.begin(); }
std::vector<Type *>::iterator param_end() { return args_.end(); }
Type *get_return_type() const;
Type *get_return_type() const;
private:
Type *result_;
Type *result_;
std::vector<Type *> args_;
};
class ArrayType : public Type {
class ArrayType : public Type
{
public:
ArrayType(Type *contained, unsigned num_elements);
......@@ -118,15 +122,16 @@ class ArrayType : public Type {
static ArrayType *get(Type *contained, unsigned num_elements);
Type *get_element_type() const { return contained_; }
Type *get_element_type() const { return contained_; }
unsigned get_num_of_elements() const { return num_elements_; }
private:
Type *contained_; // The element type of the array.
Type *contained_; // The element type of the array.
unsigned num_elements_; // Number of elements in the array.
};
class PointerType : public Type {
class PointerType : public Type
{
public:
PointerType(Type *contained);
Type *get_element_type() const { return contained_; }
......@@ -137,7 +142,8 @@ class PointerType : public Type {
Type *contained_; // The element type of the ptr.
};
class FloatType : public Type {
class FloatType : public Type
{
public:
FloatType(Module *m);
static FloatType *get(Module *m);
......@@ -145,4 +151,4 @@ class FloatType : public Type {
private:
};
#endif // SYSYC_TYPE_H
\ No newline at end of file
#endif // SYSYC_TYPE_H
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,163 +8,176 @@
#include <iostream>
#include <memory>
#ifdef DEBUG // 用于调试信息,大家可以在编译过程中通过" -DDEBUG"来开启这一选项
#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; // 输出行号的简单示例
#else
#define DEBUG_OUTPUT
#endif
#define CONST_INT(num) ConstantInt::get(num, module)
#define CONST_FP(num) ConstantFP::get(num, module) // 得到常数值的表示,方便后面多次用到
int main() {
auto module = new Module("Cminus code"); // module name是什么无关紧要
auto builder = new IRBuilder(nullptr, module);
Type *Int32Type = Type::get_int32_type(module);
// 全局数组,x,y
auto *arrayType = ArrayType::get(Int32Type, 1);
auto initializer = ConstantZero::get(Int32Type, module);
auto x = GlobalVariable::create("x", module, arrayType, false, initializer);// 参数解释: 名字name,所属module,全局变量类型type,
auto y = GlobalVariable::create("y", module, arrayType, false, initializer);// 是否是常量定义(cminus中没有常量概念,应全都是false),初始化常量(ConstantZero类)
// gcd函数
// 函数参数类型的vector
std::vector<Type *> Ints(2, Int32Type);
//通过返回值类型与参数类型列表得到函数类型
auto gcdFunTy = FunctionType::get(Int32Type, Ints);
// 由函数类型得到函数
auto gcdFun = Function::create(gcdFunTy,
"gcd", module);
// BB的名字在生成中无所谓,但是可以方便阅读
auto bb = BasicBlock::create(module, "entry", gcdFun);
builder->set_insert_point(bb); // 一个BB的开始,将当前插入指令点的位置设在bb
auto retAlloca = builder->create_alloca(Int32Type); // 在内存中分配返回值的位置
auto uAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数u的位置
auto vAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数v的位置
std::vector<Value *> args; // 获取gcd函数的形参,通过Function中的iterator
for (auto arg = gcdFun->arg_begin(); arg != gcdFun->arg_end(); arg++) {
args.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
}
builder->create_store(args[0], uAlloca); // 将参数u store下来
builder->create_store(args[1], vAlloca); // 将参数v store下来
auto vLoad = builder->create_load(vAlloca); // 将参数v load上来
auto icmp = builder->create_icmp_eq(vLoad, CONST_INT(0)); // v和0的比较,注意ICMPEQ
auto trueBB = BasicBlock::create(module, "trueBB", gcdFun); // true分支
auto falseBB = BasicBlock::create(module, "falseBB", gcdFun); // false分支
auto retBB = BasicBlock::create(
module, "", 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设置
auto uLoad = builder->create_load(uAlloca);
builder->create_store(uLoad, retAlloca);
builder->create_br(retBB); // br retBB
builder->set_insert_point(falseBB); // if false
uLoad = builder->create_load(uAlloca);
vLoad = builder->create_load(vAlloca);
auto div = builder->create_isdiv(uLoad, vLoad); // SDIV - div with S flag
auto mul = builder->create_imul(div, vLoad); // MUL - mul
auto sub = builder->create_isub(uLoad, mul); // the same
auto call = builder->create_call(gcdFun, {vLoad, sub}); // 创建call指令
// {vLoad, sub} - 参数array
builder->create_store(call, retAlloca);
builder->create_br(retBB); // br retBB
builder->set_insert_point(retBB); // ret分支
auto retLoad = builder->create_load(retAlloca);
builder->create_ret(retLoad);
// funArray函数
auto Int32PtrType = Type::get_int32_ptr_type(module); // 单个参数的类型,指针
std::vector<Type *> IntPtrs(2, Int32PtrType); // 参数列表类型
auto funArrayFunType = FunctionType::get(Int32Type, IntPtrs); // 函数类型
auto funArrayFun = Function::create(funArrayFunType, "funArray", module);
bb = BasicBlock::create(module, "entry", funArrayFun);
builder->set_insert_point(bb);
auto upAlloca = builder->create_alloca(Int32PtrType); // u的存放
auto vpAlloca = builder->create_alloca(Int32PtrType); // v的存放
auto aAlloca = builder->create_alloca(Int32Type); // a的存放
auto bAlloca = builder->create_alloca(Int32Type); // b的存放
auto tempAlloca = builder->create_alloca(Int32Type); // temp的存放
std::vector<Value *> args1; //获取funArrayFun函数的形参,通过Function中的iterator
for (auto arg = funArrayFun->arg_begin(); arg != funArrayFun->arg_end(); arg++) {
args1.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
}
builder->create_store(args1[0], upAlloca); // 将参数u store下来
builder->create_store(args1[1], vpAlloca); // 将参数v store下来
auto u0pLoad = builder->create_load(upAlloca); // 读取u
auto u0GEP = builder->create_gep(u0pLoad, {CONST_INT(0)}); // GEP: 获取u[0]地址
auto u0Load = builder->create_load(u0GEP); // 从u[0]地址 读取u[0]
builder->create_store(u0Load, aAlloca); // 将u[0] 写入 a
auto v0pLoad = builder->create_load(vpAlloca); // 同上
auto v0GEP = builder->create_gep(v0pLoad, {CONST_INT(0)});
auto v0Load = builder->create_load(v0GEP);
builder->create_store(v0Load, bAlloca);
auto aLoad = builder->create_load(aAlloca);
auto bLoad = builder->create_load(bAlloca);
icmp = builder->create_icmp_lt(aLoad, bLoad);
trueBB = BasicBlock::create(module, "trueBB", funArrayFun);
falseBB = BasicBlock::create(module, "falseBB", funArrayFun);
builder->create_cond_br(icmp, trueBB, falseBB);
builder->set_insert_point(trueBB);
builder->create_store(aLoad, tempAlloca);
builder->create_store(bLoad, aAlloca);
auto tempLoad = builder->create_load(tempAlloca);
builder->create_store(tempLoad, bAlloca);
builder->create_br(falseBB); // 注意在下一个BB之前要Br一下
builder->set_insert_point(falseBB);
aLoad = builder->create_load(aAlloca);
bLoad = builder->create_load(bAlloca);
call = builder->create_call(gcdFun, {aLoad, bLoad});
builder->create_ret(call);
// main函数
auto mainFun = Function::create(FunctionType::get(Int32Type, {}),
"main", module);
bb = BasicBlock::create(module, "entry", mainFun);
// BasicBlock的名字在生成中无所谓,但是可以方便阅读
builder->set_insert_point(bb);
retAlloca = builder->create_alloca(Int32Type);
builder->create_store(CONST_INT(0), retAlloca); // 默认 ret 0
auto x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)}); // GEP: 这里为什么是{0, 0}呢? (实验报告相关)
builder->create_store(CONST_INT(90), x0GEP);
auto y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)}); // GEP: 这里为什么是{0, 0}呢? (实验报告相关)
builder->create_store(CONST_INT(18), y0GEP);
x0GEP = builder->create_gep(x, {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}呢?
builder->create_ret(call);
// 尽管已经有很多注释,但可能还是会遇到很多bug
// 所以强烈建议配置AutoComplete,效率会大大提高!
// 如果猜不到某个IR指令对应的C++的函数,建议把指令翻译成英语然后在method列表中搜索一下。
// 最后,这个例子只涉及到了一些基本的指令生成,
// 对于额外的指令,包括数组,在之后的实验中可能需要大家自己搜索一下思考一下,
// 还有涉及到的C++语法,可以及时提问或者向大家提供指导哦!
// 对于这个例子里的代码风格/用法,如果有好的建议也欢迎提出!
std::cout << module->print();
delete module;
return 0;
/* #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 CONST_INT(num) ConstantInt::get(num, mod)
#define CONST_FP(num) \
ConstantFP::get(num, mod) // 得到常数值的表示,方便后面多次用到
int main()
{
auto mod = new Module("Cminus code"); // module name是什么无关紧要
auto builder = new IRBuilder(nullptr, mod);
Type *Int32Type = Type::get_int32_type(mod);
// 全局数组,x,y
auto *arrayType = ArrayType::get(Int32Type, 1);
auto initializer = ConstantZero::get(Int32Type, mod);
// 参数解释: 名字name,所属module,全局变量类型type,
auto x = GlobalVariable::create("x", mod, arrayType, false, initializer);
// 是否是常量定义(cminus中没有常量概念,应全都是false),初始化常量(ConstantZero类)
auto y = GlobalVariable::create("y", mod, arrayType, false, initializer);
// gcd函数
// 函数参数类型的vector
std::vector<Type *> Ints(2, Int32Type);
// 通过返回值类型与参数类型列表得到函数类型
auto gcdFunTy = FunctionType::get(Int32Type, Ints);
// 由函数类型得到函数
auto gcdFun = Function::create(gcdFunTy, "gcd", mod);
// BB的名字在生成中无所谓,但是可以方便阅读
auto bb = BasicBlock::create(mod, "entry", gcdFun);
builder->set_insert_point(bb); // 一个BB的开始,将当前插入指令点的位置设在bb
auto retAlloca =
builder->create_alloca(Int32Type); // 在内存中分配返回值的位置
auto uAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数u的位置
auto vAlloca = builder->create_alloca(Int32Type); // 在内存中分配参数v的位置
std::vector<Value *> args; // 获取gcd函数的形参,通过Function中的iterator
for (auto arg = gcdFun->arg_begin(); arg != gcdFun->arg_end(); arg++) {
args.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
}
builder->create_store(args[0], uAlloca); // 将参数u store下来
builder->create_store(args[1], vAlloca); // 将参数v store下来
auto vLoad = builder->create_load(vAlloca); // 将参数v load上来
auto icmp =
builder->create_icmp_eq(vLoad, CONST_INT(0)); // v和0的比较,注意ICMPEQ
auto trueBB = BasicBlock::create(mod, "trueBB", gcdFun); // true分支
auto falseBB = BasicBlock::create(mod, "falseBB", gcdFun); // false分支
auto retBB = BasicBlock::create(
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设置
auto uLoad = builder->create_load(uAlloca);
builder->create_store(uLoad, retAlloca);
builder->create_br(retBB); // br retBB
builder->set_insert_point(falseBB); // if false
uLoad = builder->create_load(uAlloca);
vLoad = builder->create_load(vAlloca);
auto div = builder->create_isdiv(uLoad, vLoad); // SDIV - div with S flag
auto mul = builder->create_imul(div, vLoad); // MUL - mul
auto sub = builder->create_isub(uLoad, mul); // the same
auto call = builder->create_call(gcdFun, {vLoad, sub}); // 创建call指令
// {vLoad, sub} - 参数array
builder->create_store(call, retAlloca);
builder->create_br(retBB); // br retBB
builder->set_insert_point(retBB); // ret分支
auto retLoad = builder->create_load(retAlloca);
builder->create_ret(retLoad);
// funArray函数
auto Int32PtrType = Type::get_int32_ptr_type(mod); // 单个参数的类型,指针
std::vector<Type *> IntPtrs(2, Int32PtrType); // 参数列表类型
auto funArrayFunType = FunctionType::get(Int32Type, IntPtrs); // 函数类型
auto funArrayFun = Function::create(funArrayFunType, "funArray", mod);
bb = BasicBlock::create(mod, "entry", funArrayFun);
builder->set_insert_point(bb);
auto upAlloca = builder->create_alloca(Int32PtrType); // u的存放
auto vpAlloca = builder->create_alloca(Int32PtrType); // v的存放
auto aAlloca = builder->create_alloca(Int32Type); // a的存放
auto bAlloca = builder->create_alloca(Int32Type); // b的存放
auto tempAlloca = builder->create_alloca(Int32Type); // temp的存放
std::vector<Value *>
args1; //获取funArrayFun函数的形参,通过Function中的iterator
for (auto arg = funArrayFun->arg_begin(); arg != funArrayFun->arg_end();
arg++) {
args1.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
}
builder->create_store(args1[0], upAlloca); // 将参数u store下来
builder->create_store(args1[1], vpAlloca); // 将参数v store下来
auto u0pLoad = builder->create_load(upAlloca); // 读取u
auto u0GEP =
builder->create_gep(u0pLoad, {CONST_INT(0)}); // GEP: 获取u[0]地址
auto u0Load = builder->create_load(u0GEP); // 从u[0]地址 读取u[0]
builder->create_store(u0Load, aAlloca); // 将u[0] 写入 a
auto v0pLoad = builder->create_load(vpAlloca); // 同上
auto v0GEP = builder->create_gep(v0pLoad, {CONST_INT(0)});
auto v0Load = builder->create_load(v0GEP);
builder->create_store(v0Load, bAlloca);
auto aLoad = builder->create_load(aAlloca);
auto bLoad = builder->create_load(bAlloca);
icmp = builder->create_icmp_lt(aLoad, bLoad);
trueBB = BasicBlock::create(mod, "trueBB", funArrayFun);
falseBB = BasicBlock::create(mod, "falseBB", funArrayFun);
builder->create_cond_br(icmp, trueBB, falseBB);
builder->set_insert_point(trueBB);
builder->create_store(aLoad, tempAlloca);
builder->create_store(bLoad, aAlloca);
auto tempLoad = builder->create_load(tempAlloca);
builder->create_store(tempLoad, bAlloca);
builder->create_br(falseBB); // 注意在下一个BB之前要Br一下
builder->set_insert_point(falseBB);
aLoad = builder->create_load(aAlloca);
bLoad = builder->create_load(bAlloca);
call = builder->create_call(gcdFun, {aLoad, bLoad});
builder->create_ret(call);
// main函数
auto mainFun =
Function::create(FunctionType::get(Int32Type, {}), "main", mod);
bb = BasicBlock::create(mod, "entry", mainFun);
// BasicBlock的名字在生成中无所谓,但是可以方便阅读
builder->set_insert_point(bb);
retAlloca = builder->create_alloca(Int32Type);
builder->create_store(CONST_INT(0), retAlloca); // 默认 ret 0
//
// GEP: 这里为什么是{0, 0}呢? (实验报告相关)
auto x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)});
builder->create_store(CONST_INT(90), x0GEP);
//
// GEP: 这里为什么是{0, 0}呢? (实验报告相关)
auto y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)});
builder->create_store(CONST_INT(18), y0GEP);
x0GEP = builder->create_gep(x, {CONST_INT(0), CONST_INT(0)});
y0GEP = builder->create_gep(y, {CONST_INT(0), CONST_INT(0)});
//
// 为什么这里传的是{x0GEP, y0GEP}呢?
call = builder->create_call(funArrayFun, {x0GEP, y0GEP});
builder->create_ret(call);
// 尽管已经有很多注释,但可能还是会遇到很多bug
// 所以强烈建议配置AutoComplete,效率会大大提高!
// 如果猜不到某个IR指令对应的C++的函数,建议把指令翻译成英语然后在method列表中搜索一下。
// 最后,这个例子只涉及到了一些基本的指令生成,
// 对于额外的指令,包括数组,在之后的实验中可能需要大家自己搜索一下思考一下,
// 还有涉及到的C++语法,可以及时提问或者向大家提供指导哦!
// 对于这个例子里的代码风格/用法,如果有好的建议也欢迎提出!
std::cout << mod->print();
delete mod;
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