diff --git a/.gitignore b/.gitignore index 5eaade7..d7bfd3a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ - .vscode - build +.vscode +build \ No newline at end of file diff --git a/Student/task2/cpp/assign_gen.cpp b/Student/task2/cpp/assign_gen.cpp index c30d8f1..b72c0ee 100644 --- a/Student/task2/cpp/assign_gen.cpp +++ b/Student/task2/cpp/assign_gen.cpp @@ -1,3 +1,50 @@ -int main(){ +#include "BasicBlock.h" +#include "Constant.h" +#include "Function.h" +#include "IRStmtBuilder.h" +#include "Module.h" +#include "Type.h" + +#include +#include + +#ifdef DEBUG +#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; +#else +#define DEBUG_OUTPUT +#endif + +#define CONST_INT(num) \ + ConstantInt::create(num, module) + +#define CONST_FP(num) \ + ConstantFloat::create(num, module) + +using namespace SysYF::IR; +int main() { + auto module = Module::create("SysYF code"); + auto builder = IRStmtBuilder::create(nullptr, module); + SysYF::Ptr Int32Type = Type::get_int32_type(module); + SysYF::Ptr FloatType = Type::get_float_type(module); + SysYF::Ptr ArrayType = Type::get_array_type(Int32Type, 2); + auto mainFun = Function::create(FunctionType::create(Int32Type, {}), + "main", module); + auto bb = BasicBlock::create(module, "entry", mainFun); + builder->set_insert_point(bb); + auto bAlloca = builder->create_alloca(FloatType); + auto aAlloca = builder->create_alloca(ArrayType); + builder->create_store(CONST_FP(1.8), bAlloca); + auto bLoad = builder->create_load(bAlloca); + auto a0Gep = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(0)}); + builder->create_store(CONST_INT(2), a0Gep); + auto a0Load = builder->create_load(a0Gep); + auto a0siToFp = builder->create_sitofp(a0Load, FloatType); + auto fmul = builder->create_fmul(a0siToFp, bLoad); + auto FpToSi = builder->create_fptosi(fmul, Int32Type); + auto a1Gep = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(1)}); + builder->create_store(FpToSi, a1Gep); + auto a1Load = builder->create_load(a1Gep); + builder->create_ret(a1Load); + std::cout << module->print(); return 0; } diff --git a/Student/task2/cpp/func_gen.cpp b/Student/task2/cpp/func_gen.cpp index c30d8f1..bb29a1b 100644 --- a/Student/task2/cpp/func_gen.cpp +++ b/Student/task2/cpp/func_gen.cpp @@ -1,3 +1,79 @@ -int main(){ +#include "BasicBlock.h" +#include "Constant.h" +#include "Function.h" +#include "IRStmtBuilder.h" +#include "Module.h" +#include "Type.h" + +#include +#include + +#ifdef DEBUG +#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; +#else +#define DEBUG_OUTPUT +#endif + +#define CONST_INT(num) \ + ConstantInt::create(num, module) + +#define CONST_FP(num) \ + ConstantFloat::create(num, module) + +using namespace SysYF::IR; +int main(int argc, const char * argv[]) { + auto module = Module::create("SysYF code"); + auto builder = IRStmtBuilder::create(nullptr, module); + SysYF::Ptr Int32Type = Type::get_int32_type(module); + SysYF::Ptr FloatType = Type::get_float_type(module); + SysYF::Ptr ArrayType = Type::get_array_type(Int32Type, 2); + std::vector> Ints(2, Int32Type); + //add函数 + auto addFunTy = FunctionType::create(Int32Type, Ints); + auto addFun = Function::create(addFunTy, + "add", module); + auto bb = BasicBlock::create(module, "entry", addFun); + builder->set_insert_point(bb); + auto a_add_alloc = builder->create_alloca(Int32Type); + auto b_add_alloc = builder->create_alloca(Int32Type); + auto ret_add_alloc = builder->create_alloca(Int32Type); + std::vector> args; // 获取climbStairs函数的形参,通过Function中的iterator + for (auto arg = addFun->arg_begin(); arg != addFun->arg_end(); arg++) { + args.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素 + } + builder->create_store(args[0], a_add_alloc); + builder->create_store(args[1], b_add_alloc); + auto a_add_load = builder->create_load(a_add_alloc); + auto b_add_load = builder->create_load(b_add_alloc); + auto add = builder->create_iadd(a_add_load, b_add_load); + auto sub = builder->create_isub(add, CONST_INT(1)); + builder->create_store(sub, ret_add_alloc); + auto ret_add_load = builder->create_load(ret_add_alloc); + builder->create_ret(ret_add_load); + + //main函数 + auto mainFun = Function::create(FunctionType::create(Int32Type, {}), + "main", module); + bb = BasicBlock::create(module, "entry", mainFun); + builder->set_insert_point(bb); + auto a_main_alloc = builder->create_alloca(Int32Type); + auto b_main_alloc = builder->create_alloca(Int32Type); + auto c_main_alloc = builder->create_alloca(Int32Type); + + builder->create_store(CONST_INT(2), a_main_alloc); + builder->create_store(CONST_INT(3), b_main_alloc); + builder->create_store(CONST_INT(5), c_main_alloc ); + + auto a_main_load = builder->create_load(a_main_alloc); + auto b_main_load = builder->create_load(b_main_alloc); + auto c_main_load = builder->create_load(c_main_alloc); + + auto call = builder->create_call(addFun, {a_main_load,b_main_load}); + auto add_main = builder->create_iadd(call, c_main_load); + builder->create_ret(add_main); + + std::cout << module->print(); return 0; + } + diff --git a/Student/task2/cpp/if_gen.cpp b/Student/task2/cpp/if_gen.cpp index c30d8f1..cdf6be0 100644 --- a/Student/task2/cpp/if_gen.cpp +++ b/Student/task2/cpp/if_gen.cpp @@ -1,3 +1,67 @@ -int main(){ - return 0; +#include "BasicBlock.h" +#include "Constant.h" +#include "Function.h" +#include "IRStmtBuilder.h" +#include "Module.h" +#include "Type.h" + +#include +#include + +#ifdef DEBUG // 用于调试信息,大家可以在编译过程中通过" -DDEBUG"来开启这一选项 +#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; // 输出行号的简单示例 +#else +#define DEBUG_OUTPUT +#endif + +#define CONST_INT(num) \ + ConstantInt::create(num, module) + +#define CONST_FP(num) \ + ConstantFloat::create(num, module) // 得到常数值的表示,方便后面多次用到 + +using namespace SysYF::IR; + +int main() { + auto module = Module::create("if_test.sy"); // module name是if_test + auto builder = IRStmtBuilder::create(nullptr, module); + SysYF::Ptr Int32Type = Type::get_int32_type(module); + + // 生成一个全局变量a + auto zero_initializer = ConstantZero::create(Int32Type, module); + auto a = GlobalVariable::create("a", module, Int32Type, false, zero_initializer); + + // 生成main函数 + auto mainFun = Function::create(FunctionType::create(Int32Type, {}), + "main", module); + // 生成一个基本块并进入 + auto entry = BasicBlock::create(module, "entry", mainFun); + builder->set_insert_point(entry); + + // 给a赋值给10。 + builder->create_store(CONST_INT(10), a); // store参数n + + // 把a加载到寄存器 + auto aReg = builder->create_load(a); + + // 创造一个比较语句,就是说a>0 + auto icmp = builder->create_icmp_gt(aReg, CONST_INT(0)); // n和4的比较 + + // 创造两个基本块,真 or 假 + auto trueBB = BasicBlock::create(module, "true", mainFun); // true分支 + auto falseBB = BasicBlock::create(module, "false", mainFun); // false分支 + + // 创建一个分支br + builder->create_cond_br(icmp, trueBB, falseBB); + + // 构建真的返回 + builder->set_insert_point(trueBB); + builder->create_ret(aReg); + + // 构建假的返回 + builder->set_insert_point(falseBB); + builder->create_ret(CONST_INT(0)); + + std::cout << module->print(); + return 0; } diff --git a/Student/task2/cpp/while_gen.cpp b/Student/task2/cpp/while_gen.cpp index c30d8f1..7078809 100644 --- a/Student/task2/cpp/while_gen.cpp +++ b/Student/task2/cpp/while_gen.cpp @@ -1,3 +1,84 @@ -int main(){ - return 0; +#include "BasicBlock.h" +#include "Constant.h" +#include "Function.h" +#include "IRStmtBuilder.h" +#include "Module.h" +#include "Type.h" + +#include +#include + +#ifdef DEBUG // 用于调试信息,大家可以在编译过程中通过" -DDEBUG"来开启这一选项 +#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl; // 输出行号的简单示例 +#else +#define DEBUG_OUTPUT +#endif + +#define CONST_INT(num) \ + ConstantInt::create(num, module) + +#define CONST_FP(num) \ + ConstantFloat::create(num, module) // 得到常数值的表示,方便后面多次用到 + +using namespace SysYF::IR; + +int main() { + auto module = Module::create("if_test.sy"); // module name是if_test + auto builder = IRStmtBuilder::create(nullptr, module); + SysYF::Ptr Int32Type = Type::get_int32_type(module); + + // 生成全局变量a, b + auto zero_initializer = ConstantZero::create(Int32Type, module); + auto a = GlobalVariable::create("a", module, Int32Type, false, zero_initializer); + auto b = GlobalVariable::create("b", module, Int32Type, false, zero_initializer); + + // 生成main函数 + auto mainFun = Function::create(FunctionType::create(Int32Type, {}), + "main", module); + // 生成一个基本块并进入 + auto entry = BasicBlock::create(module, "entry", mainFun); + builder->set_insert_point(entry); + + // 给b,a赋值0,3 + builder->create_store(CONST_INT(0), b); + builder->create_store(CONST_INT(3), a); + + // 设置三个BasicBlock + auto while_cond = BasicBlock::create(module, "while_cond", mainFun); + auto while_body = BasicBlock::create(module, "while_body", mainFun); + auto while_end = BasicBlock::create(module, "while_end", mainFun); + + // 跳转while_cond + builder->create_br(while_cond); + + // while_cond + builder->set_insert_point(while_cond); + // 把a加载到寄存器 + auto aReg = builder->create_load(a); + // 创造一个比较语句,就是说a>0 + auto icmp = builder->create_icmp_gt(aReg, CONST_INT(0)); // n和4的比较 + // 创建一个分支br + builder->create_cond_br(icmp, while_body, while_end); + + // while_body + builder->set_insert_point(while_body); + // b = b + 1 + auto aReg2 = builder->create_load(a); + auto bReg2 = builder->create_load(b); + auto abReg = builder->create_iadd(aReg2, bReg2); + builder->create_store(abReg, b); + // a = a - 1,此时可以优化编译流程,不重新加载a + auto aReg3 = builder->create_isub(aReg2, CONST_INT(1)); + builder->create_store(aReg3, a); + // 跳转 + builder->create_br(while_cond); + + // while_body + builder->set_insert_point(while_end); + // 构建假的返回 + auto bReg3 = builder->create_load(b); + builder->create_ret(bReg3); + + std::cout << module->print(); + return 0; } diff --git a/report/report.md b/report/report.md index 3523883..88349b0 100644 --- a/report/report.md +++ b/report/report.md @@ -11,6 +11,8 @@ 1-2 函数调用语句的格式是call @( ),包含了返回值类型,参数类型及其具体值。 +2-1 两种 LLVM IR 的不同之处在于:第一行getelementptr有4个参数,其中前两个参数分别代表数组类型和指针类型,后两个参数代表数组相对于的基址偏移量。第三个参数应当为0,代表数组的序号。因为`[10 x i32]* %1`被认为是一个指向数组的指针,所以应当首先确定该指针指向第几个数组(因为只有一个数组,因此第三个参数只能为0),然后再确定数组内部的偏移量。第二行getelementptr有3个参数,前两个参数与第一行含义相同,第三个参数等效于第一行的第四个参数,因为`i32* %1`本身就指向整形,因此只用一个参数就能确定偏移量。 + ## 实验设计 ## 实验难点及解决方案