From f5dfcd6915406eb51d3cdc70c6a1aa49b69beeba Mon Sep 17 00:00:00 2001 From: GreenDay <1072224392@qq.com> Date: Fri, 8 Dec 2023 16:11:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E9=AA=8C3=20(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Student/task3/test_stu/Dec_to_Bin.sy | 25 + Student/task3/test_stu/Fibonacci.sy | 18 + Student/task3/test_stu/poly.sy | 25 + Student/task3/test_stu/prime.sy | 30 + Student/task3/test_stu/sort.sy | 40 + report/contribution.md | 85 +- report/report.md | 31 +- src/SysYFIRBuilder/IRBuilder.cpp | 1167 +++++++++++++++++++++++++- 8 files changed, 1382 insertions(+), 39 deletions(-) create mode 100644 Student/task3/test_stu/Dec_to_Bin.sy create mode 100644 Student/task3/test_stu/Fibonacci.sy create mode 100644 Student/task3/test_stu/poly.sy create mode 100644 Student/task3/test_stu/prime.sy create mode 100644 Student/task3/test_stu/sort.sy diff --git a/Student/task3/test_stu/Dec_to_Bin.sy b/Student/task3/test_stu/Dec_to_Bin.sy new file mode 100644 index 0000000..6022f0b --- /dev/null +++ b/Student/task3/test_stu/Dec_to_Bin.sy @@ -0,0 +1,25 @@ +int a[10]; +void Dec_to_Bin(int x) +{ + int i = 0; + while(i < 10) + { + a[i] = x % 2; + x = x / 2; + i = i + 1; + } +} +int main(void) +{ + int x; + x = getint(); + Dec_to_Bin(x); + int i = 0; + while (i < 10) + { + putint(a[9-i]); + i = i + 1; + } + return 0; +} + diff --git a/Student/task3/test_stu/Fibonacci.sy b/Student/task3/test_stu/Fibonacci.sy new file mode 100644 index 0000000..74c0cab --- /dev/null +++ b/Student/task3/test_stu/Fibonacci.sy @@ -0,0 +1,18 @@ +int main() +{ + int n; + int a = 1, b = 1; + n = getint(); + + int i=0; + while(i < n/2) + { + putint(a); + putint(b); + a = a + b; + b = a + b; + i = i + 1; + } + if(n%2) putint(a); + return 0; +} diff --git a/Student/task3/test_stu/poly.sy b/Student/task3/test_stu/poly.sy new file mode 100644 index 0000000..a898b84 --- /dev/null +++ b/Student/task3/test_stu/poly.sy @@ -0,0 +1,25 @@ +int a[5]; +int poly(int x) +{ + int i=0; + int sum=0; + while(i<5) + { + sum = sum * x + a[4-i]; + i = i + 1; + } + return sum; +} +int main() +{ + int x; + x = getint(); + int i = 0; + while(i < 5) + { + a[i] = getint(); + i = i + 1; + } + return poly(x); +} + diff --git a/Student/task3/test_stu/prime.sy b/Student/task3/test_stu/prime.sy new file mode 100644 index 0000000..afbb87f --- /dev/null +++ b/Student/task3/test_stu/prime.sy @@ -0,0 +1,30 @@ +int main(void) +{ + int i = 2; + int j; + int sign; + int num=0; + while(i < 101) + { + sign = 0; + j = 2; + while( j < i ) + { + if((i % j) == 0) + { + sign = 1; + break; + } + j = j + 1; + } + if(sign == 0) + { + putint(i); + num = num + 1; + } + i = i + 1; + } + return num; +} + + diff --git a/Student/task3/test_stu/sort.sy b/Student/task3/test_stu/sort.sy new file mode 100644 index 0000000..f8b5f0a --- /dev/null +++ b/Student/task3/test_stu/sort.sy @@ -0,0 +1,40 @@ +int a[5]; +void sort() +{ + int temp,max; + int i = 0; + int j = 0; + while(i < 4) + { + j = i+1; + max = i; + while(j<5) + { + if(a[max] < a[j]) + max = j; + j = j + 1; + } + temp = a[i]; + a[i] = a[max]; + a[max] = temp; + i = i + 1; + } +} +int main() +{ + int i = 0; + while(i < 5) + { + a[i] = getint(); + i = i + 1; + } + sort(); + i = 0; + while(i < 5) + { + putint(a[i]); + putch(32); + i = i + 1; + } + return 0; +} diff --git a/report/contribution.md b/report/contribution.md index b2257ca..18d412e 100644 --- a/report/contribution.md +++ b/report/contribution.md @@ -2,16 +2,87 @@ ## 贡献详述 -### 组员1 张三 +### 组员1 舒英特 PB21111704 -### 组员2 李四 +* task1:完成文件: -### 组员3 王五 + * assign_hand.ll + * func_hand.ll + +* task2:完成文件: + + * if_gen.cpp + * while_gen.cpp + +* task3:完成模块: + + ````c++ + void IRBuilder::visit(SyntaxTree::InitVal &node) + + void IRBuilder::visit(SyntaxTree::FuncFParamList &node) + + void IRBuilder::visit(SyntaxTree::VarDef &node) + + void IRBuilder::visit(SyntaxTree::AssignStmt &node) + + void IRBuilder::visit(SyntaxTree::ReturnStmt &node) + + void IRBuilder::visit(SyntaxTree::EmptyStmt &node) + + void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) + + void IRBuilder::visit(SyntaxTree::BinaryExpr &node) + + void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) + + void IRBuilder::visit(SyntaxTree::WhileStmt &node) + + void IRBuilder::visit(SyntaxTree::ContinueStmt &node) + ```` + + 共同完成测试集设计以及问题回答 + +### 组员2 杨宇航 PB21051030 + +* Task1:完成文件: + + * if_hand.ll + * while_hand.ll + +* Task2:完成文件: + + * assign_hand.cpp + * func_hand.cpp + +* Task3:完成模块: + + ```c++ + void IRBuilder::visit(SyntaxTree::FuncDef &node) + + void IRBuilder::visit(SyntaxTree::FuncParam &node) + + void IRBuilder::visit(SyntaxTree::LVal &node) + + void IRBuilder::visit(SyntaxTree::Literal &node) + + void IRBuilder::visit(SyntaxTree::BlockStmt &node) + + void IRBuilder::visit(SyntaxTree::ExprStmt &node) + + void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) + + void IRBuilder::visit(SyntaxTree::UnaryExpr &node) + + void IRBuilder::visit(SyntaxTree::IfStmt &node) + + void IRBuilder::visit(SyntaxTree::BreakStmt &node) + ``` + + 共同完成测试集设计以及问题回答 ## 评定结果 | 组员姓名 | 贡献百分比 | -| :-----: | :-------: | -| 张三 | xx% | -| 李四 | xx% | -| 王五 | xx% | +| :------: | :--------: | +| 舒英特 | 50% | +| 杨宇航 | 50% | \ No newline at end of file diff --git a/report/report.md b/report/report.md index 88349b0..7962509 100644 --- a/report/report.md +++ b/report/report.md @@ -1,24 +1,43 @@ # PW6 实验报告 -舒英特 PB21111704 +* 舒英特 PB21111704 -杨宇航 PB21051030 +* 杨宇航 PB21051030 ## 问题回答 -1-1 一个while语句对应三个标签:第一个标签处执行判断,第二个标签处执行函数体, -第三个标签对应while的末尾。br指令有两种形式:br label a表示直接跳转到a标签处;br i1 x, label a, label b表示x是真则跳到a,x是假则跳到b。 +* 1-1 一个`while`语句对应三个标签:第一个标签处执行判断,第二个标签处执行函数体,第三个标签对应`while`的末尾。`br`指令有两种形式:`br label a`表示直接跳转到`a`标签处;`br i1 x, label a, label b`表示`x`是真则跳到`a`,`x`是假则跳到`b`。 -1-2 函数调用语句的格式是call @( ),包含了返回值类型,参数类型及其具体值。 +* 1-2 函数调用语句的格式是call @( ),包含了返回值类型,参数类型及、其具体值。 -2-1 两种 LLVM IR 的不同之处在于:第一行getelementptr有4个参数,其中前两个参数分别代表数组类型和指针类型,后两个参数代表数组相对于的基址偏移量。第三个参数应当为0,代表数组的序号。因为`[10 x i32]* %1`被认为是一个指向数组的指针,所以应当首先确定该指针指向第几个数组(因为只有一个数组,因此第三个参数只能为0),然后再确定数组内部的偏移量。第二行getelementptr有3个参数,前两个参数与第一行含义相同,第三个参数等效于第一行的第四个参数,因为`i32* %1`本身就指向整形,因此只用一个参数就能确定偏移量。 +* 2-1 两种用法的区别为,使用的指针类型不同,前者数据类型为 `i32`,指针类型为 `i32\*`,只有一个参数,表示一维的偏移量;后者数据类型为 `[10 x i32]`(数组),指针类型为 `[10 x i32]*`,有两个参数,分别表示一个维度的偏移量 + +* 3-1 在`scope`中单独处理`func`方便管理在当前作用域中的变量,方便处理局部变量以及实现整个`modul`的结构层次 ## 实验设计 +* task1:理解LLVM IR指令含义,首先将所给的sy代码翻译成单赋值中间表示,然后翻译为LLVM IR +* task2:理解提供的生成器接口,调用接口实现生成Task1中的LLVM IR +* task3:根据生成的语法树,遍历语法树的节点,补充对各个节点的访问代码,生成对应的LLVM IR + ## 实验难点及解决方案 +* 主要难点为理解生成LLVM IR模块的用法,然后对应到具体的LLVM IR语句,参考所给示例进行理解熟悉用法从而解决 +* 其次是根据对语法树结点的访问,调用正确的接口来生成对应的LLVM IR代码语句,参考PW5的形式进行解决 + ## 实验总结 +* 本次实验使我们组成员进一步了解了LLVM IR的语法 +* 本次实验使我们组员可以将课堂理论知识中的IR部分与实践相结合,理解更加透彻 +* 本次实验使我们组成员更深入理解了LLVM的部分工作原理和机制 +* 本次实验使我们组成员提升了对于C++语法中共享指针的熟练程度 + ## 实验反馈 +* task1和task2中,所需要完成翻译的sy代码都相对简单,可以考虑提供一个具体算法的代码(类似于所给demo),可以进一步加深理解 + +* task3中可以适当提供给一个实现示例,可以帮助同学们更快熟悉和理解接下来所需要完成的实验任务 + ## 组间交流 + +* 无 \ No newline at end of file diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp index 951bd45..3abeaee 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -7,11 +7,64 @@ namespace IR #define CONST_INT(num) ConstantInt::create(num, module) #define CONST_FLOAT(num) ConstantFloat::create(num, module) -// You can define global variables here -// to store state +/* 常量符号表 */ +std::list>> const_table; +//查找 +Ptr Lookup(std::string name) +{ + //首先在当前函数中从最近的scope开始寻找 + for (auto i = const_table.begin(); i != const_table.end(); i++) + { + auto iter = i->find(name); + if (iter != i->end()) + return iter->second; + } + return nullptr; +} +//将变常量插入符号表 +bool Insert(std::string name, Ptr val) +{ + //插入到当前作用域的符号表 + auto result = const_table.front().insert(std::make_pair(name, val)); + return result.second; +} +//进入新的作用域,添加新的符号表 +void make_new_table() +{ + std::map> new_table; + const_table.push_front(new_table); +} +//退出作用域,删除当前作用域的符号表 +void delete_table() +{ + const_table.pop_front(); +} // store temporary value -Ptr tmp_val = nullptr; +PtrVec Params; //函数形参类型表 +std::vector Param_names; //函数形参名表 +Ptr retAlloca = nullptr; //返回值 +Ptr retBB = nullptr; //返回语句块 +bool is_new_func = false; //判断是否为新函数,用来处理函数作用域问题 +bool get_const; //告诉LVal节点获取符号对应的常量值 +bool require_lval = false; //告诉LVal节点不需要发射load指令 +Ptr current_function = nullptr; //当前函数 +Ptr current_bb = nullptr; //当前块 +Ptr recent_value = nullptr; //最近的表达式的value +Ptr recent_ptr = nullptr; //最近的左值表达式对应变量的指针 +Ptr nextBB_while = nullptr; //while语句后的下一个基本块 +Ptr condBB_while = nullptr; //while语句cond分支 +Ptr trueBB = nullptr; //通用true分支 +Ptr falseBB = nullptr; //通用false分支 +int id = 1; //recent标号 +//初始化向量 +typedef struct InitItem +{ + bool isValue; + Ptr expr; + std::vector list; +} Inititem; +InitItem recentInitItem; // types Ptr VOID_T; @@ -21,61 +74,1123 @@ Ptr FLOAT_T; Ptr INT32PTR_T; Ptr FLOATPTR_T; -void IRBuilder::visit(SyntaxTree::Assembly &node) { +// target=val +void Assign(Ptr target, Ptr val, Ptr builder) +{ + Ptr target_type; + + if (dynamic_pointer_cast(target)) + { + target_type = (dynamic_pointer_cast(target))->get_type(); //指针 + // 这里不考虑PointerType能不能转换 + target_type = (static_pointer_cast(target_type))->get_element_type(); + } + else + { + // 这里写的可能不太严谨 + target_type = (static_pointer_cast(target))->get_alloca_type(); + } + + // int=float + if (val->get_type() == FLOAT_T && (target_type == INT32_T)) + { + auto tmp = builder->create_fptosi(val, INT32_T); + builder->create_store(tmp, target); + } + // float=int + else if (val->get_type() == INT32_T && target_type == FLOAT_T) + { + auto tmp = builder->create_sitofp(val, FLOAT_T); + builder->create_store(tmp, target); + } + else + { + builder->create_store(val, target); + } +} + +// get type from SyntaxTree +Ptr get_type(SyntaxTree::Type type, bool is_pointer) +{ + switch (type) + { + case SyntaxTree::Type::INT: + if (is_pointer) + return INT32PTR_T; + else + return INT32_T; + break; + case SyntaxTree::Type::VOID: + return VOID_T; + break; + case SyntaxTree::Type::BOOL: + return INT1_T; + break; + case SyntaxTree::Type::FLOAT: + if (is_pointer) + return FLOATPTR_T; + else + return FLOAT_T; + break; + default: + return VOID_T; + break; + } +} + +void IRBuilder::visit(SyntaxTree::Assembly &node) +{ VOID_T = Type::get_void_type(module); INT1_T = Type::get_int1_type(module); INT32_T = Type::get_int32_type(module); FLOAT_T = Type::get_float_type(module); INT32PTR_T = Type::get_int32_ptr_type(module); FLOATPTR_T = Type::get_float_ptr_type(module); - for (const auto &def : node.global_defs) { + make_new_table(); + for (const auto &def : node.global_defs) + { def->accept(*this); } } -// You need to fill them +void IRBuilder::visit(SyntaxTree::InitVal &node) +{ + InitItem newItem; + if (node.isExp) + { + node.expr->accept(*this); + newItem.isValue = true; + newItem.expr = recent_value; + } + else + { + std::vector tmp; + for (auto element : node.elementList) + { + element->accept(*this); + tmp.push_back(recentInitItem); + } + newItem.isValue = false; + newItem.list = tmp; + } + recentInitItem = newItem; +} -void IRBuilder::visit(SyntaxTree::InitVal &node) {} +void IRBuilder::visit(SyntaxTree::FuncDef &node) +{ + is_new_func = true; + Params.clear(); + Param_names.clear(); + auto ret_type = get_type(node.ret_type, false); + //获取参数列表 + if (node.param_list != NULL) + node.param_list->accept(*this); -void IRBuilder::visit(SyntaxTree::FuncDef &node) {} + //获取函数类型 + auto FunTy = FunctionType::create(ret_type, Params); + //添加函数 + auto Fun = Function::create(FunTy, node.name, module); + current_function = Fun; + scope.push(node.name, Fun); //在进入新的作用域之前添加到符号表中 -void IRBuilder::visit(SyntaxTree::FuncFParamList &node) {} + PtrVec args; // 获取函数的形参,通过Function中的iterator + for (auto arg = Fun->arg_begin(); arg != Fun->arg_end(); arg++) + args.push_back(*arg); -void IRBuilder::visit(SyntaxTree::FuncParam &node) {} + //进入函数(进入新的作用域) + scope.enter(); + make_new_table(); + auto bb = BasicBlock::create(module, "entry", Fun); + current_bb = bb; + builder->set_insert_point((Ptr )bb); + for (int i = 0; i < (int)(Param_names.size()); i++) + { + auto alloc = builder->create_alloca(Params[i]); //分配形参空间 + builder->create_store(args[i], alloc); // store 形参 + scope.push(Param_names[i], alloc); //加入作用域 + } + //创建统一return分支 + retBB = BasicBlock::create(module, "ret", Fun); + if (ret_type == VOID_T) + { + // void类型无需返回值 + current_bb = retBB; + builder->set_insert_point(retBB); + builder->create_void_ret(); + } + else + { + retAlloca = builder->create_alloca(ret_type); // 在内存中分配返回值的位置 + current_bb = retBB; + builder->set_insert_point(retBB); + auto retLoad = builder->create_load(retAlloca); + builder->create_ret(retLoad); + } + //重新回到函数开始 + current_bb = bb; + builder->set_insert_point(bb); + node.body->accept(*this); -void IRBuilder::visit(SyntaxTree::VarDef &node) {} + //处理没有return的空块 + if (!current_bb->get_terminator()) + builder->create_br(retBB); +} -void IRBuilder::visit(SyntaxTree::LVal &node) {} +void IRBuilder::visit(SyntaxTree::FuncFParamList &node) +{ + //初始化参数 + for (auto param : node.params) + { + param->accept(*this); + } +} -void IRBuilder::visit(SyntaxTree::AssignStmt &node) {} +void IRBuilder::visit(SyntaxTree::FuncParam &node) +{ + Ptr paramType = get_type(node.param_type, false); + if (!node.array_index.empty()) + { + get_const = true; + for (int i = node.array_index.size() - 1; i > 0; i--) + { + auto tmp = node.array_index[i]; + tmp->accept(*this); + paramType = ArrayType::get(paramType, (static_pointer_cast(recent_value))->get_value()); + } + get_const = false; + paramType = PointerType::get(paramType); + } + Params.push_back(paramType); + Param_names.push_back(node.name); +} + +/* 多维数组处理 */ /////////// +std::size_t depth = 0; +std::vector indexMax; +std::vector indexList; + +PtrVec tmpfor0; +PtrVec tmpforconst; +Ptr realType; + +void SetZero(Ptr alloca, std::size_t nowdepth, Ptr builder, Ptr module) +{ + if (nowdepth == indexMax.size()) + { + auto aGep = builder->create_gep(alloca, tmpfor0); + Assign(aGep, ConstantInt::create(0, module), builder); + } + else + { + for (int i = 0; i < indexMax[nowdepth]; i++) + { + tmpfor0.push_back(ConstantInt::create(i, module)); + SetZero(alloca, nowdepth + 1, builder, module); + tmpfor0.pop_back(); + } + } +} +Ptr parseConst(int nowdepth, int offset, Ptr type) +{ + if (nowdepth == (int)indexMax.size()) + return tmpforconst[offset]; + PtrVec tmp; + int blocksize = 1; + for (int i = indexMax.size() - 1; i > nowdepth; i--) + { + blocksize *= indexMax[i]; + } + for (int i = 0; i < indexMax[nowdepth]; i++) + { + tmp.push_back(parseConst(nowdepth + 1, offset + i * blocksize, type->get_array_element_type())); + } + return ConstantArray::create(static_pointer_cast(type), tmp); +} +void assignInitVal(Ptr alloca, Ptr lValType, bool isConstant, InitItem initVal, Ptr builder, Ptr module, bool firsttime) +{ + if (firsttime) + { + depth = 0; + indexMax.clear(); + indexList.clear(); + realType = lValType; + while (realType->is_array_type()) + { + indexMax.push_back((static_pointer_cast(realType))->get_num_of_elements()); + indexList.push_back(0); + realType = realType->get_array_element_type(); + } + if (alloca != NULL && lValType->is_array_type()) //局部变量置0 + { + tmpfor0.clear(); + tmpfor0.push_back(ConstantInt::create(0, module)); + SetZero(alloca, 0, builder, module); + } + if (isConstant) //要处理常数 + { + int totalnum = 1; + for (auto val : indexMax) + { + totalnum *= val; + } + tmpforconst.resize(totalnum); + for (int i = 0; i < totalnum; i++) + { + tmpforconst[i] = ConstantZero::create(realType, module); + } + } + } + //如果是常数,要返回constant*给外面的函数用 + if (!initVal.isValue) //是数组,递归操作 + { + depth++; + for (unsigned int i = 0; i < initVal.list.size(); i++) + { + int beforepos = indexList[depth - 1]; + assignInitVal(alloca, lValType->get_array_element_type(), isConstant, initVal.list[i], builder, module, false); + + bool upmatch = false; + if (beforepos == indexList[depth - 1]) + upmatch = true; + else + for (auto j = depth; j < indexList.size(); j++) + { + if (indexList[j] != 0) + { + upmatch = true; + break; + } + } + if (initVal.list[i].isValue) + upmatch = false; + if (upmatch) + { + for (auto j = depth; j < indexList.size(); j++) + { + indexList[j] = 0; + } + for (auto j = depth - 1;; j--) + { + indexList[j]++; + if (j > 0 && indexList[j] == indexMax[j]) + indexList[j] = 0; + else + break; + } + } + } + depth--; + } + else //不是数组,直接赋值 + { + if (depth < indexMax.size()) //给的初始值深度不够,自动加深 + { + depth++; + assignInitVal(alloca, lValType->get_array_element_type(), isConstant, initVal, builder, module, false); + depth--; + return; + } + + if (alloca != NULL) //非空说明是局部变量,要 + { + if (alloca->get_type()->get_pointer_element_type()->is_array_type()) //是数组,要先取指针 + { + PtrVec indexListforGep; + indexListforGep.push_back(ConstantInt::create(0, module)); + for (std::size_t i = 0; i < indexList.size(); i++) + { + indexListforGep.push_back(ConstantInt::create(indexList[i], module)); + } + auto aGep = builder->create_gep(alloca, indexListforGep); + Assign(aGep, initVal.expr, builder); + } + else + Assign(alloca, initVal.expr, builder); + } + Ptr tmp = nullptr; + if (isConstant) + { + + // float=int + if (dynamic_pointer_cast(initVal.expr) && lValType == FLOAT_T) + { + int val = (dynamic_pointer_cast(initVal.expr))->get_value(); + tmp = ConstantFloat::create((float)val, module); + } + // int=float + else if (dynamic_pointer_cast(initVal.expr) && lValType == INT32_T) + { + float val = (dynamic_pointer_cast(initVal.expr))->get_value(); + tmp = ConstantInt::create((int)val, module); + } + else + { + tmp = dynamic_pointer_cast(initVal.expr); + } + int pos = 0; + for (int i = 0; i < (int)indexMax.size(); i++) + { + pos *= indexMax[i]; + pos += indexList[i]; + } + tmpforconst[pos] = tmp; + } + //处理成功,下标++ + if (depth > 0) + { + for (auto j = depth; j < indexList.size(); j++) + { + indexList[j] = 0; + } + for (auto j = depth - 1;; j--) + { + indexList[j]++; + if (j > 0 && indexList[j] == indexMax[j]) + indexList[j] = 0; + else + break; + } + } + //处理成功,下标++ end + } +} +/* 多维数组处理 */ /////////// -void IRBuilder::visit(SyntaxTree::Literal &node) {} +void IRBuilder::visit(SyntaxTree::VarDef &node) +{ + auto name = node.name; + auto element_type = get_type(node.btype, false); + Ptr lValType; + lValType = element_type; + get_const = true; + for (int i = node.array_length.size() - 1; i >= 0; i--) + { + auto tmp = node.array_length[i]; + tmp->accept(*this); + lValType = ArrayType::get(lValType, (static_pointer_cast(recent_value))->get_value()); + } + get_const = false; + + //全局声明 + if (scope.in_global()) + { + Ptr global_alloca = nullptr; + //显式初始化 + if (node.is_inited) + { + //进入InitVal + get_const = true; + node.initializers->accept(*this); + get_const = false; + indexList.clear(); + indexMax.clear(); + depth = 0; + assignInitVal(NULL, lValType, true, recentInitItem, builder, module, true); + global_alloca = GlobalVariable::create(name, module, lValType, node.is_constant, parseConst(0, 0, lValType)); + } + //未初始化,全局变量也需要赋值为0 + else + global_alloca = GlobalVariable::create(name, module, lValType, node.is_constant, ConstantZero::create(lValType, module)); + //插入符号表 + scope.push(name, global_alloca); + //常量插入常量表 + if (node.is_constant) + Insert(name, global_alloca->get_init()); + } + //局部声明 + else + { + //分配空间并插入符号表 + auto alloca = builder->create_alloca(lValType); + scope.push(name, alloca); + //初始化 + if (node.is_inited) + { + //进入InitVal + if (node.is_constant) + get_const = true; + node.initializers->accept(*this); + get_const = false; -void IRBuilder::visit(SyntaxTree::ReturnStmt &node) {} + indexList.clear(); + indexMax.clear(); + depth = 0; + assignInitVal(alloca, lValType, node.is_constant, recentInitItem, builder, module, true); + if (node.is_constant) + { + Insert(name, parseConst(0, 0, lValType)); + } + } + } +} -void IRBuilder::visit(SyntaxTree::BlockStmt &node) {} +void IRBuilder::visit(SyntaxTree::LVal &node) +{ + bool should_return_lval = require_lval; + require_lval = false; + + auto temp = scope.find(node.name, false); + auto temp_const = Lookup(node.name); + auto lValType = temp->get_type()->get_pointer_element_type(); + //获取常量 + if (get_const) + { + recent_ptr = temp; + if (node.array_index.size() > 0) + { + for (auto tmp : node.array_index) + { + tmp->accept(*this); + if (dynamic_pointer_cast(temp_const) && dynamic_pointer_cast(recent_value)) + temp_const = (dynamic_pointer_cast(temp_const))->get_element_value((dynamic_pointer_cast(recent_value))->get_value()); + } + } + recent_value = temp_const; + } + //全局作用域访问左值一定是处理常量,所以接下来一定是局部作用域处理 + else + { + for (auto tmp : node.array_index) + { + tmp->accept(*this); + if (lValType->is_pointer_type()) + { + lValType = lValType->get_pointer_element_type(); + temp = builder->create_load(temp); + temp = builder->create_gep(temp, {recent_value}); + } + else if (lValType->is_array_type()) + { + lValType = lValType->get_array_element_type(); + temp = builder->create_gep(temp, {CONST_INT(0), recent_value}); + } + } + recent_ptr = temp; + if (lValType->is_array_type()) + recent_value = builder->create_gep(temp, {CONST_INT(0), CONST_INT(0)}); + else if (!should_return_lval) + recent_value = builder->create_load(recent_ptr); + return; + } +} + +void IRBuilder::visit(SyntaxTree::AssignStmt &node) +{ + node.value->accept(*this); + auto val = recent_value; + + require_lval = true; + node.target->accept(*this); + auto target = recent_ptr; + + Assign(target, val, builder); +} + +void IRBuilder::visit(SyntaxTree::Literal &node) +{ + if (node.literal_type == SyntaxTree::Type::INT) + { + recent_value = ConstantInt::create(node.int_const, module); + } + else if (node.literal_type == SyntaxTree::Type::FLOAT) + { + recent_value = ConstantFloat::create(node.float_const, module); + } +} + +void IRBuilder::visit(SyntaxTree::ReturnStmt &node) +{ + if (node.ret == NULL) + { + // void 返回 + recent_value = builder->create_br(retBB); + } + else + { + //先把返回值store在retAlloca中,再跳转到统一的返回入口 + node.ret->accept(*this); + /*类型转换*/ + if (recent_value->get_type() == FLOAT_T && current_function->get_return_type() == INT32_T) + { + auto temp = builder->create_fptosi(recent_value, INT32_T); + builder->create_store(temp, retAlloca); + } + else if (recent_value->get_type() == INT32_T && current_function->get_return_type() == FLOAT_T) + { + auto temp = builder->create_sitofp(recent_value, FLOAT_T); + builder->create_store(temp, retAlloca); + } + else + builder->create_store(recent_value, retAlloca); + recent_value = builder->create_br(retBB); + } +} + +void IRBuilder::visit(SyntaxTree::BlockStmt &node) +{ + //如果是一个新的函数,则不用再进入一个新的作用域 + if (is_new_func == true) + is_new_func = false; + //其它情况,需要进入一个新的作用域 + else + { + scope.enter(); + make_new_table(); + } + + //遍历每一个语句块 + for (auto stmt : node.body) + { + stmt->accept(*this); + } + scope.exit(); + delete_table(); +} void IRBuilder::visit(SyntaxTree::EmptyStmt &node) {} -void IRBuilder::visit(SyntaxTree::ExprStmt &node) {} +void IRBuilder::visit(SyntaxTree::ExprStmt &node) +{ + node.exp->accept(*this); +} + +void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) +{ + auto op = node.op; + if (op == SyntaxTree::UnaryCondOp::NOT) + { + auto temp_t = trueBB; + auto temp_f = falseBB; + trueBB = temp_f; //交换true和false + falseBB = temp_t; + node.rhs->accept(*this); + auto rhs = recent_value; + + //“非”运算的对象最终生成了br,不做处理,因为交换true和false已经完成了处理 + if (rhs->get_type() == VOID_T) + return; + // INT1-->INT32 + else if (rhs->get_type() == INT1_T) + rhs = builder->create_zext(rhs, INT32_T); + + if (rhs->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_eq(rhs, CONST_FLOAT(0)); + else + recent_value = builder->create_icmp_eq(rhs, CONST_INT(0)); + + trueBB = temp_t; + falseBB = temp_f; + } +} + +void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) +{ + auto op = node.op; + if (op == SyntaxTree::BinaryCondOp::LAND) + { + std::string id_str = std::to_string(id++); + auto bb_next = BasicBlock::create(module, id_str, current_function); + + auto temp_BB = trueBB; //保存 + trueBB = bb_next; //更新trueBB + node.lhs->accept(*this); //访问左操作数 + trueBB = temp_BB; //恢复 + + //检查返回值类型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //不是br + if (recent_value->get_type() != VOID_T) + recent_value = builder->create_cond_br(recent_value, bb_next, falseBB); + + current_bb = bb_next; + builder->set_insert_point(bb_next); + node.rhs->accept(*this); //访问右操作数 + //检查返回值类型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //不是br + if (recent_value->get_type() != VOID_T) + recent_value = builder->create_cond_br(recent_value, trueBB, falseBB); + } + else if (op == SyntaxTree::BinaryCondOp::LOR) + { + std::string id_str = std::to_string(id++); + auto bb_next = BasicBlock::create(module, id_str, current_function); + + auto temp_f = falseBB; + falseBB = bb_next; //更新falseBB + node.lhs->accept(*this); + falseBB = temp_f; + //检查返回值类型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //不是br + if (recent_value->get_type() != VOID_T) + recent_value = builder->create_cond_br(recent_value, trueBB, bb_next); + + current_bb = bb_next; + builder->set_insert_point(bb_next); + node.rhs->accept(*this); + //检查返回值类型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //不是br + if (recent_value->get_type() != VOID_T) + recent_value = builder->create_cond_br(recent_value, trueBB, falseBB); + } + else + { + node.lhs->accept(*this); //依次访问左右操作数 + auto lhs = recent_value; + node.rhs->accept(*this); + auto rhs = recent_value; + // int-->float + if (lhs->get_type() == INT32_T && rhs->get_type() == FLOAT_T) + lhs = builder->create_sitofp(lhs, FLOAT_T); + if (rhs->get_type() == INT32_T && lhs->get_type() == FLOAT_T) + rhs = builder->create_sitofp(rhs, FLOAT_T); + // int1-->int32 + if (lhs->get_type() == INT1_T && rhs->get_type() == INT32_T) + lhs = builder->create_zext(lhs, INT32_T); + if (rhs->get_type() == INT1_T && lhs->get_type() == INT32_T) + rhs = builder->create_zext(rhs, INT32_T); + // int1-->int32-->float + if (lhs->get_type() == INT1_T && rhs->get_type() == FLOAT_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + } + if (rhs->get_type() == INT1_T && lhs->get_type() == FLOAT_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + } + + if (lhs->get_type() == FLOAT_T) + { + switch (op) + { + case SyntaxTree::BinaryCondOp::EQ: + recent_value = builder->create_fcmp_eq(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::NEQ: + recent_value = builder->create_fcmp_ne(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LT: + recent_value = builder->create_fcmp_lt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LTE: + recent_value = builder->create_fcmp_le(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GT: + recent_value = builder->create_fcmp_gt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GTE: + recent_value = builder->create_fcmp_ge(lhs, rhs); + break; + default: + break; + } + } + else + { + switch (op) + { + case SyntaxTree::BinaryCondOp::EQ: + recent_value = builder->create_icmp_eq(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::NEQ: + recent_value = builder->create_icmp_ne(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LT: + recent_value = builder->create_icmp_lt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LTE: + recent_value = builder->create_icmp_le(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GT: + recent_value = builder->create_icmp_gt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GTE: + recent_value = builder->create_icmp_ge(lhs, rhs); + break; + default: + break; + } + } + } +} + +void IRBuilder::visit(SyntaxTree::BinaryExpr &node) +{ + node.lhs->accept(*this); + auto lhs = recent_value; + node.rhs->accept(*this); + auto rhs = recent_value; + auto op = node.op; + + //两边都是常数,产生constant + if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) + { + int ltmp = dynamic_pointer_cast(lhs)->get_value(); + int rtmp = dynamic_pointer_cast(rhs)->get_value(); + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = ConstantInt::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = ConstantInt::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = ConstantInt::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = ConstantInt::create(ltmp / rtmp, module); + break; + case SyntaxTree::BinOp::MODULO: + recent_value = ConstantInt::create(ltmp % rtmp, module); + break; + default: + break; + } + } + else if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) + { + float ltmp = dynamic_pointer_cast(lhs)->get_value(); + float rtmp = dynamic_pointer_cast(rhs)->get_value(); + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = ConstantFloat::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = ConstantFloat::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = ConstantFloat::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = ConstantFloat::create(ltmp / rtmp, module); + break; + default: + break; + } + } + else if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) + { + int ltmp = dynamic_pointer_cast(lhs)->get_value(); + float rtmp = dynamic_pointer_cast(rhs)->get_value(); + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = ConstantFloat::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = ConstantFloat::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = ConstantFloat::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = ConstantFloat::create(ltmp / rtmp, module); + break; + default: + break; + } + } + else if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) + { + float ltmp = dynamic_pointer_cast(lhs)->get_value(); + int rtmp = dynamic_pointer_cast(rhs)->get_value(); + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = ConstantFloat::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = ConstantFloat::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = ConstantFloat::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = ConstantFloat::create(ltmp / rtmp, module); + break; + default: + break; + } + } + else + { + // int-->float + if (lhs->get_type() == INT32_T && rhs->get_type() == FLOAT_T) + lhs = builder->create_sitofp(lhs, FLOAT_T); + if (rhs->get_type() == INT32_T && lhs->get_type() == FLOAT_T) + rhs = builder->create_sitofp(rhs, FLOAT_T); + // int1-->int32 + if (lhs->get_type() == INT1_T && rhs->get_type() == INT32_T) + lhs = builder->create_zext(lhs, INT32_T); + if (rhs->get_type() == INT1_T && lhs->get_type() == INT32_T) + rhs = builder->create_zext(rhs, INT32_T); + // int1-->int32-->float + if (lhs->get_type() == INT1_T && rhs->get_type() == FLOAT_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + } + if (rhs->get_type() == INT1_T && lhs->get_type() == FLOAT_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + } + + //结果为int + if (rhs->get_type() == INT32_T) + { + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = builder->create_iadd(lhs, rhs); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = builder->create_isub(lhs, rhs); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = builder->create_imul(lhs, rhs); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = builder->create_isdiv(lhs, rhs); + break; + case SyntaxTree::BinOp::MODULO: + recent_value = builder->create_isrem(lhs, rhs); + break; + default: + break; + } + } + //结果为float + else + { + switch (op) + { + case SyntaxTree::BinOp::PLUS: + recent_value = builder->create_fadd(lhs, rhs); + break; + case SyntaxTree::BinOp::MINUS: + recent_value = builder->create_fsub(lhs, rhs); + break; + case SyntaxTree::BinOp::MULTIPLY: + recent_value = builder->create_fmul(lhs, rhs); + break; + case SyntaxTree::BinOp::DIVIDE: + recent_value = builder->create_fdiv(lhs, rhs); + break; + default: + break; + } + } + } +} + +void IRBuilder::visit(SyntaxTree::UnaryExpr &node) +{ + node.rhs->accept(*this); + auto rhs = recent_value; + auto op = node.op; + + if (dynamic_pointer_cast(rhs) && op == SyntaxTree::UnaryOp::MINUS) + { + int tmp = dynamic_pointer_cast(rhs)->get_value(); + recent_value = ConstantInt::create(-1 * tmp, module); + } + else if (dynamic_pointer_cast(rhs) && op == SyntaxTree::UnaryOp::MINUS) + { + float tmp = dynamic_pointer_cast(rhs)->get_value(); + recent_value = ConstantFloat::create(-1.0 * tmp, module); + } + else + { + // INT1-->INT32 + if (rhs->get_type() == INT1_T) + rhs = builder->create_zext(rhs, INT32_T); + + if (op == SyntaxTree::UnaryOp::MINUS) + { + if (rhs->get_type() == FLOAT_T) + recent_value = builder->create_fmul(rhs, CONST_FLOAT(-1)); + else + recent_value = builder->create_imul(rhs, CONST_INT(-1)); + } + } +} + +void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) +{ + Ptr Fun = static_pointer_cast(scope.find(node.name, true)); + //获取函数的形参,用于类型检查 + PtrVec args; + for (auto arg = Fun->arg_begin(); arg != Fun->arg_end(); arg++) + args.push_back(*arg); + //实参列表生成 + int i = 0; + PtrVec func_args; //函数调用实参列表 + for (auto param : node.params) + { + param->accept(*this); + // int-->float + if (recent_value->get_type() == INT32_T && args[i]->get_type() == FLOAT_T) + { + auto tmp = builder->create_sitofp(recent_value, FLOAT_T); + func_args.push_back(tmp); + } + // float-->int + else if (recent_value->get_type() == FLOAT_T && args[i]->get_type() == INT32_T) + { + auto tmp = builder->create_fptosi(recent_value, INT32_T); + func_args.push_back(tmp); + } + else + { + func_args.push_back(recent_value); + } + i++; + } + recent_value = builder->create_call(Fun, func_args); +} -void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) {} +void IRBuilder::visit(SyntaxTree::IfStmt &node) +{ + //进入if结点的时候要先存储之前的trueBB和falseBB,退出结点的时候恢复 + auto temp_t = trueBB; + auto temp_f = falseBB; + + std::string id_str; + id_str = std::to_string(id++); + trueBB = BasicBlock::create(module, id_str, current_function); // true分支 + id_str = std::to_string(id++); + falseBB = BasicBlock::create(module, id_str, current_function); // false分支 + // if语句后的下一个基本块 + Ptr nextBB_if; + if (node.else_statement != nullptr) + { + id_str = std::to_string(id++); + nextBB_if = BasicBlock::create(module, id_str, current_function); + } + else + nextBB_if = falseBB; + + node.cond_exp->accept(*this); //访问条件表达式 + //检查返回值是否为bool型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //如果已经发射了br指令,则recent_value->get_type() == VOID_T,不做处理 + if (recent_value->get_type() != VOID_T) + builder->create_cond_br(recent_value, trueBB, falseBB); + + bool next = false; -void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) {} + current_bb = trueBB; + builder->set_insert_point(trueBB); // if true + node.if_statement->accept(*this); + if (!current_bb->get_terminator()) + { + next = true; //nextBB_if可达 + builder->create_br(nextBB_if); + } -void IRBuilder::visit(SyntaxTree::BinaryExpr &node) {} + //存在else分支 + if (node.else_statement != nullptr) + { + current_bb = falseBB; + builder->set_insert_point(falseBB); + node.else_statement->accept(*this); + if (!current_bb->get_terminator()) + { + next = true; //nextBB_if可达 + builder->create_br(nextBB_if); + } + } -void IRBuilder::visit(SyntaxTree::UnaryExpr &node) {} + //nextBB_if不可达 + if (!next && node.else_statement) + nextBB_if->erase_from_parent(); + else + { + current_bb = nextBB_if; + builder->set_insert_point(nextBB_if); + } -void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) {} + trueBB = temp_t; + falseBB = temp_f; +} -void IRBuilder::visit(SyntaxTree::IfStmt &node) {} +void IRBuilder::visit(SyntaxTree::WhileStmt &node) +{ + //进入while结点的时候要先缓存之前的基本块 + auto temp_condBB = condBB_while; + auto temp_trueBB = trueBB; + auto temp_falseBB = falseBB; + auto temp_nextBB_while = nextBB_while; -void IRBuilder::visit(SyntaxTree::WhileStmt &node) {} + std::string id_str; + id_str = std::to_string(id++); + condBB_while = BasicBlock::create(module, id_str, current_function); // 条件BB + id_str = std::to_string(id++); + trueBB = BasicBlock::create(module, id_str, current_function); // true分支 + id_str = std::to_string(id++); + falseBB = BasicBlock::create(module, id_str, current_function); // false分支 + nextBB_while = falseBB; -void IRBuilder::visit(SyntaxTree::BreakStmt &node) {} + builder->create_br(condBB_while); + current_bb = condBB_while; + builder->set_insert_point(condBB_while); + node.cond_exp->accept(*this); //访问条件表达式 + //检查返回值是否为bool型 + if (recent_value->get_type() == INT32_T) + recent_value = builder->create_icmp_ne(recent_value, CONST_INT(0)); + else if (recent_value->get_type() == FLOAT_T) + recent_value = builder->create_fcmp_ne(recent_value, CONST_FLOAT(0)); + //如果已经发射了br指令,则recent_value->get_type() == VOID_T,不做处理 + if (recent_value->get_type() != VOID_T) + builder->create_cond_br(recent_value, trueBB, falseBB); -void IRBuilder::visit(SyntaxTree::ContinueStmt &node) {} + current_bb = trueBB; + builder->set_insert_point(trueBB); + node.statement->accept(*this); + if (!current_bb->get_terminator()) + builder->create_br(condBB_while); + + current_bb = nextBB_while; + builder->set_insert_point(nextBB_while); + + //退出while结点的时候要恢复之前的基本块 + condBB_while = temp_condBB; + trueBB = temp_trueBB; + falseBB = temp_falseBB; + nextBB_while = temp_nextBB_while; +} + +void IRBuilder::visit(SyntaxTree::BreakStmt &node) +{ + recent_value = builder->create_br(nextBB_while); +} + +void IRBuilder::visit(SyntaxTree::ContinueStmt &node) +{ + recent_value = builder->create_br(condBB_while); +} } } \ No newline at end of file