#include "IRBuilder.h" #include #include #include #define DEBUG #ifdef DEBUG #define DBGLOG(text) std::cout << text << std::endl #define DEBUG_OUTPUT ; #endif #ifndef DEBUG #define DBGLOG(text) #define DEBUG_OUTPUT std::cout << __LINE__ << std::endl #endif namespace SysYF { 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 typedef struct { bool is_int; int ival; float fval; } Oprand; Oprand expr_cal_result; // 便于全局变量中表达式计算值中转 std::vector multi_arr_init; class GlobalConst { public: GlobalConst() {} ~GlobalConst() = default; void add_int_const(std::string name, int val) { if (iconst_map.find(name) == iconst_map.end()) { // 新加入的不是数组元素 std::vector temp(1, val); iconst_map.insert(std::make_pair(name, temp)); } else // 新加入的是数组元素 iconst_map[name].push_back(val); } void add_float_const(std::string name, float val) { if (fconst_map.find(name) == fconst_map.end()) { // 新加入的不是数组元素 std::vector temp(1, val); fconst_map.insert(std::make_pair(name, temp)); } else // 新加入的是数组元素 fconst_map[name].push_back(val); } bool get_int_const(std::string name, int offset, int &val) // 若非数组则offset=0 { if (iconst_map.find(name) != iconst_map.end()) { val = iconst_map[name][offset]; return true; } else return false; } bool get_float_const(std::string name, int offset, float &val) { if (fconst_map.find(name) != fconst_map.end()) { val = fconst_map[name][offset]; return true; } else return false; } private: std::map> iconst_map; std::map> fconst_map; }; GlobalConst _const_table = GlobalConst(); std::vector> FuncParas; SysYF::Ptr Para; std::string name_; std::vector names; int Ifnum = 0; int ReturnNum = 0; Ptr retAlloca; SysYF::Ptr retbb; /* enum Condtype { equal, greater, less, ge, le, notequal }condtype_; */ /* SysYF::Ptr _cmp; */ // store temporary value Ptr tmp_val = nullptr; // 存储需要全局处理的expr node Ptr lhs_addr = nullptr; Ptr func_parent; // 便于在创建新的bb时获得对应的func_parent int bb_label_num = 0; // 全局控制bb标签编号 bool func_first_bb; // 处理一个func域里有多个{},只创建一个scope PtrVec break_point; PtrVec continue_point; // 维护两个vector(栈)控制循环break和continue应跳转到的目标地址 // types Ptr VOID_T; Ptr INT1_T; Ptr INT32_T; Ptr FLOAT_T; Ptr INT32PTR_T; Ptr FLOATPTR_T; 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) { def->accept(*this); } } // You need to fill them void IRBuilder::visit(SyntaxTree::InitVal &node) { /* DBGLOG("Begin of Initval"); */ // 可能有一个或多个value需要初始化,elementList方便迭代accept if (node.isExp) { node.expr->accept(*this); multi_arr_init.push_back(expr_cal_result); } else { for (auto item : node.elementList) { item->accept(*this); } } /* DBGLOG("End of Initval"); */ } void IRBuilder::visit(SyntaxTree::FuncDef &node) { /* DBGLOG("Begin of FuncDef"); */ Ptr RetType; switch (node.ret_type) { case SysYF::SyntaxTree::Type::VOID: RetType = VOID_T; break; case SysYF::SyntaxTree::Type::INT: RetType = INT32_T; break; case SysYF::SyntaxTree::Type::FLOAT: RetType = FLOAT_T; break; default: break; } node.param_list->accept(*this); auto FuncTY = FunctionType::create(RetType, FuncParas); auto Func = Function::create(FuncTY, node.name, module); func_parent = Func; // 标记当前func_parent(便于后续bb调用) scope.push(node.name, Func); scope.enter(); auto bb = BasicBlock::create(module, node.name + "_entry", Func); builder->set_insert_point(bb); func_first_bb = true; // 设置为第一次进入该func的bb{} ReturnNum = 0; if (RetType != VOID_T) { retAlloca = builder->create_alloca(RetType); if (RetType == INT32_T) builder->create_store(CONST_INT(0), retAlloca); else if (RetType == FLOAT_T) builder->create_store(CONST_FLOAT(0), retAlloca); } std::vector> args; for (auto arg = Func->arg_begin(); arg != Func->arg_end(); arg++) { args.push_back(*arg); } for (size_t i = 0; i < names.size(); i++) { auto pAlloca = builder->create_alloca(FuncParas[i]); builder->create_store(args[i], pAlloca); scope.push(names[i], pAlloca); } retbb = BasicBlock::create(module, node.name + "_ret", Func); node.body->accept(*this); if (!builder->get_insert_block()->get_terminator()) builder->create_br(retbb); builder->set_insert_point(retbb); if (RetType == VOID_T) { builder->create_void_ret(); } else { auto retLoad = builder->create_load(retAlloca); builder->create_ret(retLoad); } /* builder->create_br(retbb); */ /* scope.exit(); */ /* DBGLOG("End of FuncDef"); */ } void IRBuilder::visit(SyntaxTree::FuncFParamList &node) { FuncParas.clear(); names.clear(); for (auto &p : node.params) { p->accept(*this); FuncParas.push_back(Para); names.push_back(name_); } assert(FuncParas.size() == names.size()); } void IRBuilder::visit(SyntaxTree::FuncParam &node) { name_ = node.name; if (node.array_index.size()) { // 数组 if (node.param_type == SysYF::SyntaxTree::Type::INT) Para = INT32PTR_T; else if (node.param_type == SysYF::SyntaxTree::Type::FLOAT) Para = FLOATPTR_T; } else { // 非数组 if (node.param_type == SysYF::SyntaxTree::Type::INT) Para = INT32_T; else if (node.param_type == SysYF::SyntaxTree::Type::FLOAT) Para = FLOAT_T; } } void IRBuilder::visit(SyntaxTree::VarDef &node) { /* DBGLOG("Begin of VarDef"); */ // 变量定义:判断是否是全局变量,判断是否是const,判断是否是数组类型 // 获取变量类型和变量名字,分配变量存储空间,若有需要初始化变量 Ptr vartype; if (node.btype == SyntaxTree::Type::INT) vartype = INT32_T; else vartype = FLOAT_T; // if分级判断逻辑:全局or局部->数组or单变量->const of 非const(本次实验不涉及局部数组常量)->初始化or未初始化 if (scope.in_global()) // 全局变量 { if (!node.array_length.empty()) // 数组类型 { // 目前只考虑一维数组,多维数组需要处理vector类型的array_length得到各维度长度 std::vector arr_len; unsigned total_ = 1; for (int i = 0; i < node.array_length.size(); i++) { node.array_length[i]->accept(*this); arr_len.push_back(expr_cal_result.ival); total_ *= expr_cal_result.ival; } Ptr arr_type = ArrayType::create(vartype, total_); if (node.is_inited) { PtrVec init_val; // 待push_back,多维转线性排列 int last_dim = arr_len.back(); int line_idx = 0; for (auto val : node.initializers->elementList) // 每一个val都是一个InitVal,可能是expr,也可能是elementlist { multi_arr_init.clear(); val->accept(*this); for (int i = 0; i < multi_arr_init.size(); i++) { Oprand tmp = multi_arr_init[i]; if (vartype == INT32_T) { int temp = (tmp.is_int) ? tmp.ival : int(tmp.fval); init_val.push_back(std::static_pointer_cast(CONST_INT(temp))); if (node.is_constant) _const_table.add_int_const(node.name, temp); } else if (vartype == FLOAT_T) { float temp = (tmp.is_int) ? float(tmp.ival) : tmp.fval; init_val.push_back(std::static_pointer_cast(CONST_FLOAT(temp))); if (node.is_constant) _const_table.add_float_const(node.name, temp); } } } // 全局变量剩余部分初始化为0 for (int i = init_val.size(); i < arr_len; i++) { if (vartype == INT32_T) { init_val.push_back(std::static_pointer_cast(CONST_INT(0))); if (node.is_constant) _const_table.add_int_const(node.name, 0); } else if (vartype == FLOAT_T) { init_val.push_back(std::static_pointer_cast(CONST_FLOAT(0))); if (node.is_constant) _const_table.add_float_const(node.name, 0.0f); } } auto initializer = ConstantArray::create(arr_type, init_val); auto Global_array = GlobalVariable::create(node.name, module, arr_type, node.is_constant, std::static_pointer_cast(initializer)); scope.push(node.name, Global_array); } else // 未显式初始化,全为0 { if (node.is_constant) { for (int i = 0; i < arr_len; i++) { if (vartype == INT32_T) _const_table.add_int_const(node.name, 0); else _const_table.add_float_const(node.name, 0.0f); } } auto initializer = ConstantZero::create(arr_type, module); auto Global_array = GlobalVariable::create(node.name, module, arr_type, node.is_constant, std::static_pointer_cast(initializer)); scope.push(node.name, Global_array); } } else // 单变量 { if (node.is_inited) { // 只能是Ptr类型 node.initializers->expr->accept(*this); Ptr init_val; if (vartype == INT32_T) { int temp = (expr_cal_result.is_int) ? expr_cal_result.ival : int(expr_cal_result.fval); init_val = std::static_pointer_cast(CONST_INT(temp)); if (node.is_constant) _const_table.add_int_const(node.name, temp); } else if (vartype == FLOAT_T) { float temp = (expr_cal_result.is_int) ? float(expr_cal_result.ival) : expr_cal_result.fval; init_val = std::static_pointer_cast(CONST_FLOAT(temp)); if (node.is_constant) _const_table.add_float_const(node.name, temp); } auto Global_val = GlobalVariable::create(node.name, module, vartype, node.is_constant, init_val); scope.push(node.name, Global_val); } else { if (node.is_constant) { if (vartype == INT32_T) _const_table.add_int_const(node.name, 0); else _const_table.add_float_const(node.name, 0.0f); } auto init_val = ConstantZero::create(vartype, module); auto Global_val = GlobalVariable::create(node.name, module, vartype, node.is_constant, std::static_pointer_cast(init_val)); scope.push(node.name, Global_val); } } } else // 局部变量 { if (!node.array_length.empty()) // 数组类型(不考虑const数组) { node.array_length[0]->accept(*this); int arr_len = expr_cal_result.ival; /* DBGLOG(arr_len); */ Ptr arr_type = ArrayType::get(vartype, arr_len); /* Ptr arr_type = PointerType::get(vartype); */ auto arr_val_alloca = builder->create_alloca(arr_type); if (node.is_inited) // 若未显式初始化,则初始值未知 { /* DBGLOG(node.initializers->elementList.size()); */ int arrIdx = 0; // gep类指令计算每个元素地址 for (auto val : node.initializers->elementList) { val->expr->accept(*this); // 此时的类型转换IR指令为显式的 if (tmp_val->get_type() != vartype) // tmp_val为Ptr类型,便于生成类型转换IR { if (vartype == INT32_T) tmp_val = builder->create_fptosi(tmp_val, INT32_T); else tmp_val = builder->create_sitofp(tmp_val, FLOAT_T); } // 根据初始化值store到对应的gep地址中 auto val_addr = builder->create_gep(arr_val_alloca, {CONST_INT(0), CONST_INT(arrIdx)}); builder->create_store(tmp_val, val_addr); arrIdx++; } } scope.push(node.name, arr_val_alloca); } else // 单变量, tmp_val便于发射类型转换ir,expr_cal_result便于维护常量表 { auto var_alloca = builder->create_alloca(vartype); if (node.is_inited) { node.initializers->expr->accept(*this); if (tmp_val->get_type() != vartype) { if (vartype == INT32_T) tmp_val = builder->create_fptosi(tmp_val, INT32_T); else tmp_val = builder->create_sitofp(tmp_val, FLOAT_T); } if (node.is_constant) { if (vartype == INT32_T) { int temp = (expr_cal_result.is_int) ? expr_cal_result.ival : int(expr_cal_result.fval); _const_table.add_int_const(node.name, temp); } else { float temp = (expr_cal_result.is_int) ? float(expr_cal_result.ival) : expr_cal_result.fval; _const_table.add_float_const(node.name, temp); } } builder->create_store(tmp_val, var_alloca); } scope.push(node.name, var_alloca); } } /* DBGLOG("End of VarDef"); */ } void IRBuilder::visit(SyntaxTree::LVal &node) { /* DBGLOG("Begin of LVal"); */ /* DBGLOG(node.name); */ if (scope.in_global()) // 在全局变量初始化时,InitVal 中的初始值为 Exp时可以引用左值变量 { /* DBGLOG("Begin of LVal if"); */ int tmp1; float tmp2; int offset = 0; if (!node.array_index.empty()) { // 暂时只考虑一维数组 node.array_index[0]->accept(*this); offset = expr_cal_result.ival; } if (_const_table.get_int_const(node.name, offset, tmp1)) { expr_cal_result.is_int = true; expr_cal_result.ival = tmp1; } else if (_const_table.get_float_const(node.name, offset, tmp2)) { expr_cal_result.is_int = false; expr_cal_result.fval = tmp2; } } else // 并非处于全局域,左值为被赋值对象(store)或赋值对象(load)(函数调用的情形在funcall里处理) { /* DBGLOG("Begin of LVal else"); */ auto lval_addr = scope.find(node.name, false); bool IsArray = false; if (!node.array_index.empty()) // 数组左值, 需要先发射gep指令,再发射load指令 { /* DBGLOG("array"); */ node.array_index[0]->accept(*this); assert(lval_addr != nullptr); /* DBGLOG(node.name); DBGLOG(lval_addr->get_type()->get_type_id()); */ // DEBUG_OUTPUT; if (lval_addr->get_type()->get_pointer_element_type()->is_array_type()) // 左值非指针 { /* DBGLOG("In LVal array"); */ // a[4] auto lval = builder->create_gep(lval_addr, {CONST_INT(0), tmp_val}); lhs_addr = lval; tmp_val = builder->create_load(lval); IsArray = true; } else // 左值是指针 { //(*a)[4] auto ptr = builder->create_load(lval_addr); auto lval = builder->create_gep(ptr, {tmp_val}); // 没有CONST_INT(0),基址是ptr lhs_addr = lval; tmp_val = builder->create_load(lval); } } else if (lval_addr->get_type()->get_pointer_element_type()->is_pointer_type()) { //*a tmp_val = builder->create_load(lval_addr); // load得到的是指针值 lhs_addr = lval_addr; } else { // a tmp_val = builder->create_load(lval_addr); lhs_addr = lval_addr; } } /* DBGLOG("End of LVal"); */ } void IRBuilder::visit(SyntaxTree::AssignStmt &node) { /* DBGLOG("Begin of Assign"); */ /* DBGLOG(node.target->name); */ node.target->accept(*this); auto lhs = tmp_val; auto lhs_addr_ = lhs_addr; node.value->accept(*this); auto rhs = tmp_val; auto lhstype = lhs->get_type(); // 获左值类型 /* DBGLOG(lhstype->get_type_id()); */ auto rhstype = rhs->get_type(); /* DBGLOG(rhstype->get_type_id()); */ // 检查是否需要显式类型转换和符号扩展ir指令 if (rhstype == INT1_T) { rhs = builder->create_zext(rhs, INT32_T); rhstype = INT32_T; } if (lhstype != rhstype) { if (lhstype == INT32_T) rhs = builder->create_fptosi(rhs, INT32_T); else { /* DBGLOG("create "); */ rhs = builder->create_sitofp(rhs, FLOAT_T); } } builder->create_store(rhs, lhs_addr_); /* DBGLOG("End of Assign"); */ } void IRBuilder::visit(SyntaxTree::Literal &node) { /* DBGLOG("Begin of Literal"); */ if (node.literal_type == SyntaxTree::Type::INT) { tmp_val = CONST_INT(node.int_const); expr_cal_result.is_int = true; expr_cal_result.ival = node.int_const; } else if (node.literal_type == SyntaxTree::Type::FLOAT) { tmp_val = CONST_FLOAT(node.float_const); expr_cal_result.is_int = false; expr_cal_result.fval = node.float_const; } else { // DBGLOG("error at literal"); } /* DBGLOG("End of Literal"); */ } void IRBuilder::visit(SyntaxTree::ReturnStmt &node) { /* DBGLOG("Begin of Return"); */ auto RetType = builder->get_insert_block()->get_parent()->get_return_type(); /* auto funName = builder->get_insert_block()->get_parent()->get_name(); char num_[10]; sprintf(num_, "%d", ReturnNum++); */ /* retbb = BasicBlock::create(module, funName + "_ret_" + num_, func_parent); */ if (!RetType->is_void_type()) { node.ret->accept(*this); auto tmpType = tmp_val->get_type(); /* builder->create_br(retbb); builder->set_insert_point(retbb); */ if (tmpType != RetType) { if (RetType == FLOAT_T) { if (tmpType == INT1_T) // INT1 to INT32 tmp_val = builder->create_zext(tmp_val, INT32_T); // INT32 to FLOAT tmp_val = builder->create_sitofp(tmp_val, FLOAT_T); } else if (RetType == INT32_T) { // INT1 to INT32 if (tmpType == INT1_T) tmp_val = builder->create_zext(tmp_val, INT32_T); else if (tmpType == FLOAT_T) // FLOAT to INT32 tmp_val = builder->create_fptosi(tmp_val, INT32_T); } } builder->create_store(tmp_val, retAlloca); } builder->create_br(retbb); /* DBGLOG("End of Return"); */ } void IRBuilder::visit(SyntaxTree::BlockStmt &node) { if (func_first_bb == true) func_first_bb = false; // 后续不是firstbb else scope.enter(); for (auto stmt : node.body) { stmt->accept(*this); } scope.exit(); } void IRBuilder::visit(SyntaxTree::EmptyStmt &node) {} void IRBuilder::visit(SyntaxTree::ExprStmt &node) { node.exp->accept(*this); } void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) { // 返回icmp或/fcmp与0相比的结果到全局变量tmp_val,发射对应ir指令 node.rhs->accept(*this); auto rhs = tmp_val; auto rhstype = rhs->get_type(); if (node.op == SyntaxTree::UnaryCondOp::NOT) // 只有!非号需要处理,否则不形成UnaryCondExpr结点 { if (rhstype->is_integer_type()) // 整型分1bit和32bit { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_eq(CONST_INT(0), zext); } else tmp_val = builder->create_icmp_eq(CONST_INT(0), rhs); } else if (rhstype->is_float_type()) tmp_val = builder->create_fcmp_eq(CONST_FLOAT(0), rhs); else // rhs是指针类型 tmp_val = CONST_INT(true); // true 则为非零值 } } void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) { Ptr lhs, rhs; Ptr lhstype, rhstype; if ((node.op != SyntaxTree::BinaryCondOp::LAND) && (node.op != SyntaxTree::BinaryCondOp::LOR)) { node.lhs->accept(*this); lhs = tmp_val; lhstype = lhs->get_type(); node.rhs->accept(*this); rhs = tmp_val; rhstype = rhs->get_type(); } switch (node.op) { case SyntaxTree::BinaryCondOp::LT: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_lt(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_lt(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_lt(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_lt(lhs, rhs); } break; case SyntaxTree::BinaryCondOp::LTE: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_le(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_le(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_le(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_le(lhs, rhs); } break; case SyntaxTree::BinaryCondOp::GT: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_gt(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_gt(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_gt(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_gt(lhs, rhs); } break; case SyntaxTree::BinaryCondOp::GTE: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_ge(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_ge(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_ge(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_ge(lhs, rhs); } break; case SyntaxTree::BinaryCondOp::EQ: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_eq(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_eq(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_eq(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_eq(lhs, rhs); } break; case SyntaxTree::BinaryCondOp::NEQ: if (lhstype->is_float_type() && rhstype->is_float_type()) { tmp_val = builder->create_fcmp_ne(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_icmp_ne(lhs, rhs); } else if (lhstype->is_float_type()) { if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); rhs = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fcmp_ne(lhs, rhs); } else if (rhstype->is_float_type()) { if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); lhs = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fcmp_ne(lhs, rhs); } break; // 非常关键的控制流语句br(逻辑与/或) case SyntaxTree::BinaryCondOp::LAND: // lhs和rhs都应该是INT1_T { auto parent = func_parent; char labelname[20]; sprintf(labelname, "true_bb_%d", bb_label_num++); // lhs&&rhs为true进入执行体 auto true_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "false_bb_%d", bb_label_num++); // lhs为false(应该就是after cond bb吧?也可能进入下一个cond bb) auto false_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "next_bb_%d", bb_label_num++); // rhs判断域 auto next_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "after_bb_%d", bb_label_num++); // auto after_bb = BasicBlock::create(module, labelname, parent); auto result = builder->create_alloca(INT1_T); node.lhs->accept(*this); lhs = tmp_val; lhstype = lhs->get_type(); if (Type::is_eq_type(lhstype, INT1_T)) { builder->create_cond_br(lhs, next_bb, false_bb); // if true直接跳转到nextbb(rhs判断的bb),否则跳转到falsebb } else if (Type::is_eq_type(lhstype, INT32_T)) { tmp_val = builder->create_icmp_ne(lhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(lhs, next_bb, false_bb); } else if (Type::is_eq_type(lhstype, FLOAT_T)) { tmp_val = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, next_bb, false_bb); } else // 为无条件跳转 { builder->create_br(next_bb); } builder->set_insert_point(next_bb); // rhs判断域 node.rhs->accept(*this); rhs = tmp_val; rhstype = rhs->get_type(); if (Type::is_eq_type(rhstype, INT1_T)) { builder->create_cond_br(rhs, true_bb, false_bb); // if true直接跳转到truebb,否则跳转到falsebb } else if (Type::is_eq_type(rhstype, INT32_T)) { tmp_val = builder->create_icmp_ne(rhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(rhs, true_bb, false_bb); } else if (Type::is_eq_type(rhstype, FLOAT_T)) { tmp_val = builder->create_fcmp_ne(rhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, true_bb, false_bb); } else // 为无条件跳转 { builder->create_br(true_bb); } builder->set_insert_point(true_bb); // cond_bb判断域结束,进入true_bb执行体内部 builder->create_store(CONST_INT(true), result); builder->create_br(after_bb); builder->set_insert_point(false_bb); builder->create_store(CONST_INT(false), result); builder->create_br(after_bb); // true_bb和false_bb IR结束后都要无条件br到after_bb builder->set_insert_point(after_bb); tmp_val = builder->create_load(result); break; } case SyntaxTree::BinaryCondOp::LOR: // lhs和rhs都应该是INT1_T, 与LAND稍有区别(使用短路计算) auto parent = func_parent; char labelname[20]; sprintf(labelname, "ture_bb_%d", bb_label_num++); // lhs&&rhs为true进入执行体 auto true_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "false_bb_%d", bb_label_num++); // lhs为false(应该就是after cond bb吧?也可能进入下一个cond bb) auto false_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "next_bb_%d", bb_label_num++); // rhs判断域 auto next_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "after_bb_%d", bb_label_num++); // auto after_bb = BasicBlock::create(module, labelname, parent); auto result = builder->create_alloca(INT1_T); node.lhs->accept(*this); lhs = tmp_val; lhstype = lhs->get_type(); if (Type::is_eq_type(lhstype, INT1_T)) { builder->create_cond_br(lhs, true_bb, next_bb); // if true直接跳转到turebb执行体内,否则跳转到nextbb(rhs判断域) } else if (Type::is_eq_type(lhstype, INT32_T)) { tmp_val = builder->create_icmp_ne(lhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, true_bb, next_bb); } else if (Type::is_eq_type(lhstype, FLOAT_T)) { tmp_val = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, true_bb, next_bb); } else // 为无条件跳转 { builder->create_br(true_bb); } builder->set_insert_point(next_bb); // rhs判断域 node.rhs->accept(*this); rhs = tmp_val; rhstype = rhs->get_type(); if (Type::is_eq_type(rhstype, INT1_T)) { builder->create_cond_br(rhs, true_bb, false_bb); // if true直接跳转到truebb,否则跳转到falsebb } else if (Type::is_eq_type(rhstype, INT32_T)) { tmp_val = builder->create_icmp_ne(rhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, true_bb, false_bb); } else if (Type::is_eq_type(rhstype, FLOAT_T)) { tmp_val = builder->create_fcmp_ne(rhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假 builder->create_cond_br(tmp_val, true_bb, false_bb); } else // 为无条件跳转 { builder->create_br(true_bb); } builder->set_insert_point(true_bb); // cond_bb判断域结束,进入true_bb执行体内部 builder->create_store(CONST_INT(true), result); builder->create_br(after_bb); builder->set_insert_point(false_bb); builder->create_store(CONST_INT(false), result); builder->create_br(after_bb); // true_bb和false_bb IR结束后都要无条件br到after_bb builder->set_insert_point(after_bb); tmp_val = builder->create_load(result); break; } } void IRBuilder::visit(SyntaxTree::BinaryExpr &node) { if (scope.in_global()) // 需要计算全局变量声明中某些表达式 { int lhs_ival, rhs_ival; float lhs_fval, rhs_fval; bool lhs_is_int, rhs_is_int; node.lhs->accept(*this); if (expr_cal_result.is_int) lhs_ival = expr_cal_result.ival; else lhs_fval = expr_cal_result.fval; lhs_is_int = expr_cal_result.is_int; node.rhs->accept(*this); if (expr_cal_result.is_int) rhs_ival = expr_cal_result.ival; else rhs_fval = expr_cal_result.fval; rhs_is_int = expr_cal_result.is_int; switch (node.op) { case SyntaxTree::BinOp::PLUS: if (lhs_is_int && rhs_is_int) { expr_cal_result.is_int = true; expr_cal_result.ival = lhs_ival + rhs_ival; } else if (!lhs_is_int && rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval + rhs_ival; } else if (lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_ival + rhs_fval; } else if (!lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval + rhs_fval; } break; case SyntaxTree::BinOp::MINUS: if (lhs_is_int && rhs_is_int) { expr_cal_result.is_int = true; expr_cal_result.ival = lhs_ival - rhs_ival; } else if (!lhs_is_int && rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval - rhs_ival; } else if (lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_ival - rhs_fval; } else if (!lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval - rhs_fval; } break; case SyntaxTree::BinOp::MULTIPLY: if (lhs_is_int && rhs_is_int) { expr_cal_result.is_int = true; expr_cal_result.ival = lhs_ival * rhs_ival; } else if (!lhs_is_int && rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval * rhs_ival; } else if (lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_ival * rhs_fval; } else if (!lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval * rhs_fval; } break; case SyntaxTree::BinOp::DIVIDE: if (lhs_is_int && rhs_is_int) { expr_cal_result.is_int = true; expr_cal_result.ival = lhs_ival / rhs_ival; } else if (!lhs_is_int && rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval / rhs_ival; } else if (lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_ival / rhs_fval; } else if (!lhs_is_int && !rhs_is_int) { expr_cal_result.is_int = false; expr_cal_result.fval = lhs_fval / rhs_fval; } break; case SyntaxTree::BinOp::MODULO: expr_cal_result.is_int = true; if (lhs_is_int && rhs_is_int) expr_cal_result.ival = lhs_ival % rhs_ival; else if (!lhs_is_int && rhs_is_int) expr_cal_result.fval = int(lhs_fval) % rhs_ival; else if (lhs_is_int && !rhs_is_int) expr_cal_result.fval = lhs_ival % int(rhs_fval); else if (!lhs_is_int && !rhs_is_int) expr_cal_result.fval = int(lhs_fval) % int(rhs_fval); break; } } else // 生成相应计算ir指令, 根据最终指令形式分为float、int和指针计算三种 { node.lhs->accept(*this); auto lhs = tmp_val; auto lhstype = lhs->get_type(); node.rhs->accept(*this); auto rhs = tmp_val; auto rhstype = rhs->get_type(); switch (node.op) { case SyntaxTree::BinOp::PLUS: if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T)) { // 目标ir为float加法 if (lhstype->is_integer_type()) // 类型不匹配 { if (Type::is_eq_type(lhstype, INT1_T)) { auto zext = builder->create_zext(lhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fadd(itof, rhs); } else { auto itof = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fadd(itof, rhs); } } else if (rhstype->is_integer_type()) { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fadd(lhs, itof); } else { auto itof = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fadd(lhs, itof); } } else tmp_val = builder->create_fadd(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { // 目标ir为32位加法 if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_iadd(lhs, rhs); } else { // 目标ir为指针计算(地址计算gep) PtrVec ptr_idx; // 为适配多维数组或结构体的多个idx寻址,设置为vector类型 if (lhstype->is_pointer_type()) { ptr_idx.push_back(rhs); tmp_val = builder->create_gep(lhs, ptr_idx); } else if (rhstype->is_pointer_type()) { ptr_idx.push_back(lhs); tmp_val = builder->create_gep(rhs, ptr_idx); } } break; case SyntaxTree::BinOp::MINUS: if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T)) { // 目标ir为float减法 if (lhstype->is_integer_type()) // 类型不匹配 { if (Type::is_eq_type(lhstype, INT1_T)) { auto zext = builder->create_zext(lhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fsub(itof, rhs); } else { auto itof = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fsub(itof, rhs); } } else if (rhstype->is_integer_type()) { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fsub(lhs, itof); } else { auto itof = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fsub(lhs, itof); } } else tmp_val = builder->create_fsub(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { // 目标ir为32位减法 if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_isub(lhs, rhs); } else { // 目标ir为指针计算(地址计算gep), 只能lhs为指针类型 PtrVec ptr_idx; // 为适配多维数组或结构体的多个idx寻址,设置为vector类型 if (lhstype->is_pointer_type()) { ptr_idx.push_back(rhs); tmp_val = builder->create_gep(lhs, ptr_idx); } } break; case SyntaxTree::BinOp::MULTIPLY: if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T)) { // 目标ir为float乘法 if (lhstype->is_integer_type()) // 类型不匹配 { if (Type::is_eq_type(lhstype, INT1_T)) { auto zext = builder->create_zext(lhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fmul(itof, rhs); } else { auto itof = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fmul(itof, rhs); } } else if (rhstype->is_integer_type()) { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fmul(lhs, itof); } else { auto itof = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fmul(lhs, itof); } } else tmp_val = builder->create_fmul(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { // 目标ir为32位乘法 if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_imul(lhs, rhs); } break; case SyntaxTree::BinOp::DIVIDE: if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T)) { // 目标ir为float除法 if (lhstype->is_integer_type()) // 类型不匹配 { if (Type::is_eq_type(lhstype, INT1_T)) { auto zext = builder->create_zext(lhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fdiv(itof, rhs); } else { auto itof = builder->create_sitofp(lhs, FLOAT_T); tmp_val = builder->create_fdiv(itof, rhs); } } else if (rhstype->is_integer_type()) { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); auto itof = builder->create_sitofp(zext, FLOAT_T); tmp_val = builder->create_fdiv(lhs, itof); } else { auto itof = builder->create_sitofp(rhs, FLOAT_T); tmp_val = builder->create_fdiv(lhs, itof); } } else tmp_val = builder->create_fdiv(lhs, rhs); } else if (lhstype->is_integer_type() && rhstype->is_integer_type()) { // 目标ir为32位除法 if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_isdiv(lhs, rhs); } break; case SyntaxTree::BinOp::MODULO: // 取模运算只能是int类型(不能通过ir将float类型转换,这是不合法的) if (lhstype->is_integer_type() && rhstype->is_integer_type()) { // 目标ir为32位取模 if (Type::is_eq_type(lhstype, INT1_T)) lhs = builder->create_zext(lhs, INT32_T); if (Type::is_eq_type(rhstype, INT1_T)) rhs = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_isrem(lhs, rhs); } break; } } } void IRBuilder::visit(SyntaxTree::UnaryExpr &node) { if (scope.in_global()) // 需要计算全局变量声明中某些表达式 { // 只有minus需要修改值,否则值和类型都不用修改 node.rhs->accept(*this); if (expr_cal_result.is_int) { if (node.op == SyntaxTree::UnaryOp::MINUS) expr_cal_result.ival = -expr_cal_result.ival; else if (node.op == SyntaxTree::UnaryOp::MINUS) expr_cal_result.fval = -expr_cal_result.fval; } } else // 需要更新tmp_val { node.rhs->accept(*this); auto rhs = tmp_val; auto rhstype = rhs->get_type(); switch (node.op) { case SyntaxTree::UnaryOp::PLUS: break; case SyntaxTree::UnaryOp::MINUS: if (rhstype->is_integer_type()) { if (Type::is_eq_type(rhstype, INT1_T)) { auto zext = builder->create_zext(rhs, INT32_T); tmp_val = builder->create_isub(CONST_INT(0), zext); } else tmp_val = builder->create_isub(CONST_INT(0), rhs); } else if (rhstype->is_float_type()) tmp_val = builder->create_fsub(CONST_FLOAT(0), rhs); break; } } } void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) { auto Func = dynamic_pointer_cast(scope.find(node.name, true)); auto RetType = Func->get_return_type(); PtrVec param; param.clear(); auto FuncPara = Func->get_args(); int idx = 0; // DBGLOG("begin the funccall"); for (auto funp : FuncPara) { node.params[idx]->accept(*this); auto tmpType = tmp_val->get_type(); auto ParaType = funp->get_type(); if (ParaType == tmpType) param.push_back(tmp_val); else if (ParaType == INT32_T) { switch (tmpType->get_type_id()) { // INT1 to INT32 case SysYF::IR::Type::TypeID::IntegerTyID: tmp_val = builder->create_zext(tmp_val, INT32_T); param.push_back(tmp_val); break; // FLOAT to INT32 case SysYF::IR::Type::TypeID::FloatTyID: tmp_val = builder->create_fptosi(tmp_val, INT32_T); param.push_back(tmp_val); break; // other default: // DBGLOG("Error type to INT32_T"); // DBGLOG(tmpType->get_type_id()); break; } } else if (ParaType == FLOAT_T) { switch (tmpType->get_type_id()) { // INT1/32 to FLOAT case SysYF::IR::Type::TypeID::IntegerTyID: if (tmpType == INT1_T) tmp_val = builder->create_zext(tmp_val, INT32_T); tmp_val = builder->create_sitofp(tmp_val, FLOAT_T); param.push_back(tmp_val); break; // other default: // DBGLOG("Error type to FLOAT_T"); // DBGLOG(tmpType->get_type_id()); break; } } else if (ParaType->is_pointer_type()) { if (tmpType->is_array_type()) { // DBGLOG(tmpType->get_type_id()); // DBGLOG("debug 1"); auto Element_pointer = builder->create_gep(lhs_addr, {CONST_INT(0), CONST_INT(0)}); // DBGLOG("debug 2"); param.push_back(Element_pointer); } else { // DBGLOG("ParaType == pointer"); // DBGLOG(tmpType->get_type_id()); } } else { // DBGLOG("Error ParaType"); // DBGLOG(ParaType->get_type_id()); // other } idx++; } if (RetType == VOID_T) { builder->create_call(Func, param); } else { tmp_val = builder->create_call(Func, param); } // DBGLOG("end the funccall"); } void IRBuilder::visit(SyntaxTree::IfStmt &node) { /* DBGLOG("begin the IF"); */ SysYF::Ptr bbTrue, bbAfter, bbFalse, bbCond; auto ParentFunc = builder->get_insert_block()->get_parent(); char num[10]; // itoa(Ifnum, num, 10); /* DBGLOG("before the sprintf"); */ sprintf(num, "%d", Ifnum++); /* DBGLOG("after the sprintf"); */ /* std::string s = "if_cond_"; bbCond = BasicBlock::create(module, s + num, ParentFunc); */ std::string s = "if_true_"; bbTrue = BasicBlock::create(module, s + num, ParentFunc); if (node.else_statement) { s = "if_false_"; bbFalse = BasicBlock::create(module, s + num, ParentFunc); } s = "after_if_"; bbAfter = BasicBlock::create(module, s + num, ParentFunc); /* DBGLOG("before visit cond"); */ /* builder->create_br(bbCond); */ /* builder->set_insert_point(bbCond); */ node.cond_exp->accept(*this); /* DBGLOG("after visit cond"); */ SysYF::Ptr _cmp; auto condType = tmp_val->get_type(); if (condType == INT1_T) _cmp = tmp_val; else if (condType == INT32_T) _cmp = builder->create_icmp_ne(tmp_val, CONST_INT(0)); else if (condType == FLOAT_T) _cmp = builder->create_fcmp_ne(tmp_val, CONST_FLOAT(0)); else { } /* DBGLOG("after Init cmp"); */ if (!_cmp) builder->create_br(bbTrue); else if (node.else_statement) builder->create_cond_br(_cmp, bbTrue, bbFalse); else builder->create_cond_br(_cmp, bbTrue, bbAfter); builder->set_insert_point(bbTrue); /* DBGLOG("before visit if_stmt"); */ node.if_statement->accept(*this); /* DBGLOG("after visit if_stmt"); */ if (!builder->get_insert_block()->get_terminator()) builder->create_br(bbAfter); if (node.else_statement) { builder->set_insert_point(bbFalse); /* DBGLOG("before visit else"); */ node.else_statement->accept(*this); if (!builder->get_insert_block()->get_terminator()) builder->create_br(bbAfter); } builder->set_insert_point(bbAfter); /* DBGLOG("end the IF"); */ } void IRBuilder::visit(SyntaxTree::WhileStmt &node) { // 类比condexpr和ifstmt,需要创建bb label并控制跳转 char labelname[20]; auto parent = func_parent; sprintf(labelname, "cond_bb_%d", bb_label_num++); auto cond_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "true_bb_%d", bb_label_num++); auto true_bb = BasicBlock::create(module, labelname, parent); sprintf(labelname, "after_bb_%d", bb_label_num++); auto after_bb = BasicBlock::create(module, labelname, parent); break_point.push_back(after_bb); // break后直接跳转至afterbb(循环语句后紧接的bb) continue_point.push_back(cond_bb); // continue后跳转至条件判断域condbb builder->create_br(cond_bb); // 进入AST的whilrnode后先无条件进行一次条件判断 builder->set_insert_point(cond_bb); node.cond_exp->accept(*this); auto cond_judge = tmp_val; auto cond_type = cond_judge->get_type(); // 只有当cond是INT1_T类型时才能直接生成cond_br, 否则要先判断cond是否为零值 if (Type::is_eq_type(cond_type, INT1_T)) { builder->create_cond_br(cond_judge, true_bb, after_bb); } else if (Type::is_eq_type(cond_type, INT32_T)) { cond_judge = builder->create_icmp_ne(cond_judge, CONST_INT(0)); builder->create_cond_br(cond_judge, true_bb, after_bb); } else if (Type::is_eq_type(cond_type, FLOAT_T)) { cond_judge = builder->create_fcmp_ne(cond_judge, CONST_FLOAT(0)); builder->create_cond_br(cond_judge, true_bb, after_bb); } else // 说明能无条件跳转, while(1) { builder->create_br(true_bb); } builder->set_insert_point(true_bb); // 进入循环执行体内部生成IR node.statement->accept(*this); // 访问循环体内部stmt, 自会生成IR if (!(builder->get_insert_block()->get_terminator())) // ret与br都是Terminator Instructions也就是终止指令, 若没有则补充(while语句里没有) builder->create_br(cond_bb); builder->set_insert_point(after_bb); // 离开前别忘了维护break和continue栈 break_point.pop_back(); continue_point.pop_back(); } void IRBuilder::visit(SyntaxTree::BreakStmt &node) { // 控制跳转目的地址 char labelname[20]; auto parent = func_parent; sprintf(labelname, "break_dest_%d", bb_label_num++); auto break_dest_bb = BasicBlock::create(module, labelname, parent); builder->create_br(break_point.back()); // 还不需要pop, while语句中会pop builder->set_insert_point(break_dest_bb); } void IRBuilder::visit(SyntaxTree::ContinueStmt &node) { // 控制跳转目的地址 char labelname[20]; auto parent = func_parent; sprintf(labelname, "cond_dest_%d", bb_label_num++); auto cond_dest_bb = BasicBlock::create(module, labelname, parent); builder->create_br(continue_point.back()); // 还不需要pop, while语句中会pop builder->set_insert_point(cond_dest_bb); } } }