diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp index 951bd45..c19d7d5 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -1,81 +1,1787 @@ #include "IRBuilder.h" +#include + +// #define DEBUG +#ifdef DEBUG +#define LOG(output) std::cout << output << std::endl + +#endif +#ifndef DEBUG +#define LOG(output) +#endif + +#define ERROR(error) std::cerr << error << std::endl namespace SysYF { -namespace IR -{ + 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 - -// store temporary value -Ptr tmp_val = nullptr; - -// 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 can define global variables here + // to store state + GlobalVar GlobalVar_ = GlobalVar(); + std::vector> continue_addr; // from outside to inside of the continue + std::vector> break_addr; // from outside to inside of the continue + Ptr now_func; // 当前函数 + std::vector> param_type_list; // 形参类型列表 + bool func_block; // 是否是函数最外层块 + bool get_literal; + + Ptr exp_val; // 表达式分析出的值 + Ptr left_val; // 左值 + Ptr ret_addr; // 返回地址 + int label_num; // 每次需要label时自增一,编号 + // store temporary value + Ptr tmp_val = nullptr; + Ptr ret_bb; + // 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) // vardef中 + { + LOG("_initval"); + LOG("in initval elementlist size: " << node.elementList.size()); + // 输出elementlist + + // for (auto element : node.elementList) + // { + // LOG(element->isExp); + // element->accept(*this); + // } + + if (node.isExp) // 初始化表达式 + // { + // node.exp->accept(*this); + // } + // else//初始化列表 + // { + // for(const auto &initVal:node.init_list) + // { + // initVal->accept(*this); + // } + // } + { + LOG("here"); + node.expr->accept(*this); + } + LOG("initval done"); + } + + void IRBuilder::visit(SyntaxTree::FuncDef &node) + { + LOG("_funcdef"); + Ptr ret_type; // 返回值类型 + if (node.ret_type == SyntaxTree::Type::VOID) + { + ret_type = VOID_T; + LOG("funcdef:ret type is void"); + } + else if (node.ret_type == SyntaxTree::Type::INT) + { + ret_type = INT32_T; + LOG("funcdef:ret type is int"); + } + else if (node.ret_type == SyntaxTree::Type::FLOAT) + { + ret_type = FLOAT_T; + LOG("funcdef:ret type is float"); + } + else + { + ERROR("error:funcdef unknown return type"); + exit(1); + } + // 参数 + node.param_list->accept(*this); + + // 创建函数 + auto func_type = FunctionType::create(ret_type, param_type_list); + auto func = Function::create(func_type, node.name, module); + LOG("Create function: " + node.name); + // 进入当前函数域 + now_func = func; + // 加入scope + scope.push(node.name, func); + scope.enter(); + LOG("enter"); + // 创建入口基本块 + auto funcBB = BasicBlock::create(module, node.name + "funcBB", func); + builder->set_insert_point(funcBB); + // 函数第一个语句 + func_block = true; + // 为返回值分配空间 + if (ret_type != VOID_T) + { + auto retAlloca = builder->create_alloca(ret_type); + ret_addr = retAlloca; + builder->create_store(CONST_INT(0), ret_addr); // 初始化为0 + } + + // 创建retBB + auto retBB = BasicBlock::create(module, node.name + "retBB", func); + ret_bb = retBB; + // 参数记录到符号表 + std::vector> args; + for (auto arg = func->arg_begin(); arg != func->arg_end(); arg++) + { + args.push_back(*arg); + } + // 为参数分配空间 + LOG("args size: " << args.size()); + int paramIndex = 0; + for (auto param : node.param_list->params) + { + auto argAlloca = builder->create_alloca(param_type_list[paramIndex]); + builder->create_store(args[paramIndex], argAlloca); + scope.push(param->name, argAlloca); + paramIndex++; + } + // 函数体 + node.body->accept(*this); + LOG("funcdef body done"); + + // 处理return + if (builder->get_insert_block()->get_terminator() == nullptr) // 没有return语句 + { + LOG("funcdef no return"); + // 缺省 + builder->create_br(ret_bb); // 直接跳转到retBB + } + builder->set_insert_point(retBB); // 进入retBB + // 下面对应label_ret后的内容 + if (ret_type->is_void_type()) + { // void + builder->create_void_ret(); + LOG("funcdef void ret"); + } + else + { // 非void + LOG("funcdef non-void ret"); + auto retLoad = builder->create_load(ret_type, ret_addr); // 对应load语句 + builder->create_ret(retLoad); // 对应ret语句 + } + } + + void IRBuilder::visit(SyntaxTree::FuncFParamList &node) + { + LOG("_funcfparamlist"); + param_type_list = std::vector>(); // 清空 + int debug_cnt = 0; + for (auto param : node.params) + { + LOG("funcfparamlist:" << debug_cnt++); + param->accept(*this); + } + } -// You need to fill them + void IRBuilder::visit(SyntaxTree::FuncParam &node) + { + LOG("_funcparam"); + if (node.array_index.size() == 0) // 不是数组元素 + { + if (node.param_type == SyntaxTree::Type::INT) + { + param_type_list.push_back(INT32_T); + } + else if (node.param_type == SyntaxTree::Type::FLOAT) + { + param_type_list.push_back(FLOAT_T); + } + else + { + ERROR("error:funcdef unknown param type"); + exit(1); + } + } + // 一维数组 + else if (node.array_index.size() == 1) + { + if (node.param_type == SyntaxTree::Type::INT) + { + param_type_list.push_back(INT32PTR_T); + } + else if (node.param_type == SyntaxTree::Type::FLOAT) + { + param_type_list.push_back(FLOATPTR_T); + } + else + { + ERROR("error:funcdef unknown param type"); + exit(1); + } + } + // 多维数组 + // + } -void IRBuilder::visit(SyntaxTree::InitVal &node) {} + void IRBuilder::visit(SyntaxTree::VarDef &node) + { + LOG("_vardef"); + Ptr var_type; + if (node.btype == SyntaxTree::Type::INT) + { + var_type = INT32_T; + } + else if (node.btype == SyntaxTree::Type::FLOAT) + { + var_type = FLOAT_T; + } + else + { + ERROR("error:vardef unknown type"); + exit(1); + } + // 是否是全局变量 + if (scope.in_global()) + { + LOG("vardef in global"); + // 是全局变量 + if (node.array_length.size() == 0) + { + // 不是数组 + if (node.is_inited) + { // 初始化 + LOG("global var initialed"); -void IRBuilder::visit(SyntaxTree::FuncDef &node) {} + node.initializers->accept(*this); + Ptr init_val; + if (var_type == INT32_T) + { + LOG("ival"); + int ival; + if (GlobalVar_.is_int()) + { + LOG("is int"); + ival = GlobalVar_.pop_int(); + init_val = CONST_INT(ival); + LOG("initial INT"); + } + else + { + LOG("is float"); + ival = GlobalVar_.pop_float(); + init_val = CONST_INT(ival); + } + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, ival); + } + } + else + { + float fval; + if (GlobalVar_.is_int()) + { + fval = GlobalVar_.pop_int(); + init_val = CONST_FLOAT(fval); + } + else + { + fval = GlobalVar_.pop_float(); + init_val = CONST_FLOAT(fval); + } + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, fval); + } + } + auto global_val = GlobalVariable::create(node.name, module, var_type, node.is_constant, init_val); + scope.push(node.name, global_val); + } + else // 未初始化 + { + auto global_val = GlobalVariable::create(node.name, module, var_type, node.is_constant, ConstantZero::create(var_type, module)); + if (node.is_constant) + { + if (var_type == INT32_T) + { + GlobalVar_.insertConst(node.name, 0); + } + else + { + GlobalVar_.insertConst(node.name, float(0.0)); + } + } + scope.push(node.name, global_val); + } + } + else if (node.array_length.size() == 1) + // 一维数组 + { + SyntaxTree::Expr *arr_len_1 = node.array_length[0].get(); + arr_len_1->accept(*this); // 数组长度 literal + int arr_len = 0; + if (GlobalVar_.is_int()) + { + arr_len = GlobalVar_.pop_int(); + LOG("arr_len: " << arr_len); // ok + } + else + { + ERROR("error:array length is not int"); + } + auto arr_type = ArrayType::get(var_type, arr_len); + if (node.is_inited) + { + node.initializers->accept(*this); // visit initval + std::vector> init_val; + for (auto val : node.initializers->elementList) + { + if (val->isExp) // 一维数组这行应成立 + { + val->expr->accept(*this); + if (var_type == INT32_T) + { + int ival; + if (GlobalVar_.is_int()) + { + ival = GlobalVar_.pop_int(); + init_val.push_back(CONST_INT(ival)); + } + else + { + ival = GlobalVar_.pop_float(); + init_val.push_back(CONST_INT(ival)); + } + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, ival); + } + } + else + { + float fval; + if (GlobalVar_.is_int()) + { + fval = GlobalVar_.pop_int(); + init_val.push_back(CONST_FLOAT(fval)); + } + else + { + fval = GlobalVar_.pop_float(); + init_val.push_back(CONST_FLOAT(fval)); + } + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, fval); + } + } + LOG("init_val.size: " << init_val.size()); + } + else + { + ERROR("error:array init is not exp"); + } + } + // 未初始化部分初始化为0 + for (int i = init_val.size(); i < arr_len; i++) + { + if (var_type == INT32_T) + { + init_val.push_back(CONST_INT(0)); + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, 0); + } + } + else + { + init_val.push_back(CONST_FLOAT(0.0)); + if (node.is_constant) + { + GlobalVar_.insertConst(node.name, float(0.0)); + } + } + } -void IRBuilder::visit(SyntaxTree::FuncFParamList &node) {} + auto init_arr = ConstantArray::create(arr_type, init_val); -void IRBuilder::visit(SyntaxTree::FuncParam &node) {} + auto global_arr = GlobalVariable::create(node.name, module, arr_type, node.is_constant, init_arr); + scope.push(node.name, global_arr); + } -void IRBuilder::visit(SyntaxTree::VarDef &node) {} + else // 未初始化 + { + auto init_arr = ConstantArray::create(arr_type, std::vector>(arr_len, ConstantZero::create(var_type, module))); + auto global_arr = GlobalVariable::create(node.name, module, arr_type, node.is_constant, init_arr); + scope.push(node.name, global_arr); + } + } + } -void IRBuilder::visit(SyntaxTree::LVal &node) {} + else + { + // 不是全局变量 + if (node.array_length.size() == 0) + { + // 不是数组 + auto varAlloca = builder->create_alloca(var_type); -void IRBuilder::visit(SyntaxTree::AssignStmt &node) {} + if (node.is_inited) + { // 初始化 + node.initializers->accept(*this); + if (exp_val->get_type() != var_type) + { + if (var_type == FLOAT_T) + { + exp_val = builder->create_sitofp(exp_val, FLOAT_T); + LOG("init cast int to float"); + } + else + { + exp_val = builder->create_fptosi(exp_val, INT32_T); + LOG("init cast float to int"); + } + } -void IRBuilder::visit(SyntaxTree::Literal &node) {} + builder->create_store(exp_val, varAlloca); + } -void IRBuilder::visit(SyntaxTree::ReturnStmt &node) {} + else // 未初始化 + { + builder->create_store(ConstantZero::create(var_type, module), varAlloca); + } + scope.push(node.name, varAlloca); + } + else if (node.array_length.size() == 1) // 一维数组 + { + SyntaxTree::Expr *arr_len_1 = node.array_length[0].get(); // 数组长度 + get_literal = true; // + arr_len_1->accept(*this); + get_literal = false; // + int arr_len; + if (GlobalVar_.is_int()) + { + arr_len = GlobalVar_.pop_int(); + } + else + { + ERROR("error:array length is not int"); + } + auto arr_type = ArrayType::get(var_type, arr_len); + auto varAlloca = builder->create_alloca(arr_type); + if (node.is_inited) + { + int arrIndex = 0; + node.initializers->accept(*this); // visit vardef + std::vector> init_val; + for (auto val : node.initializers->elementList) + { + if (val->isExp) // 一维数组这行应成立 + { + val->expr->accept(*this); + if (exp_val->get_type() != var_type) + { + if (var_type == FLOAT_T) + { + exp_val = builder->create_sitofp(exp_val, FLOAT_T); + LOG("init cast int to float"); + } + else + { + exp_val = builder->create_fptosi(exp_val, INT32_T); + LOG("init cast float to int"); + } + } + auto Gep = builder->create_gep(varAlloca, {CONST_INT(0), CONST_INT(arrIndex++)}); // 获取数组元素地址 + builder->create_store(exp_val, Gep); + } + } + } + scope.push(node.name, varAlloca); + } + } + } -void IRBuilder::visit(SyntaxTree::BlockStmt &node) {} + void IRBuilder::visit(SyntaxTree::LVal &node) + { + LOG("_lval"); + if (scope.in_global() || get_literal) + { + if (node.array_index.size() == 0) + { + GlobalVar_.pushConst(node.name, 0); + } + else if (node.array_index.size() == 1) + { + node.array_index[0]->accept(*this); + int offset; + if (GlobalVar_.is_int()) + { + offset = GlobalVar_.pop_int(); + } + else + { + offset = GlobalVar_.pop_float(); + LOG("????"); + } + GlobalVar_.pushConst(node.name, offset); + } + } + else + { + LOG("use lval:" << node.name); + auto lval_addr = scope.find(node.name, false); + if (node.array_index.size() == 1) + { // 一维数组 + node.array_index[0]->accept(*this); + if (lval_addr->get_type()->get_pointer_element_type()->is_array_type()) + { // 指针类型 + auto gep = builder->create_gep(lval_addr, {CONST_INT(0), exp_val}); + left_val = gep; + exp_val = builder->create_load(gep); + } + else + { // 作为左值 + auto lval_p = builder->create_load(lval_addr); + auto gep = builder->create_gep(lval_p, {exp_val}); // 偏移操作 + left_val = gep; + // 作为表达式,需要load + exp_val = builder->create_load(gep); + } -void IRBuilder::visit(SyntaxTree::EmptyStmt &node) {} + auto offset = exp_val; + auto gep = builder->create_gep(lval_addr, {CONST_INT(0), offset}); + left_val = gep; + } + else if (node.array_index.size() == 0) + { + if (lval_addr->get_type()->get_pointer_element_type()->is_array_type()) + { //////????? + left_val = lval_addr; + exp_val = builder->create_gep(lval_addr, {CONST_INT(0), CONST_INT(0)}); + LOG("array as lval"); + } + else if (lval_addr->get_type()->get_pointer_element_type()->is_pointer_type()) + { + // 指针类型 + left_val = lval_addr; + exp_val = builder->create_load(lval_addr); + LOG("pointer as lval"); + } + else + { -void IRBuilder::visit(SyntaxTree::ExprStmt &node) {} + left_val = lval_addr; + exp_val = builder->create_load(lval_addr); + LOG("normal as lval"); + } + } + } + } -void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) {} + void IRBuilder::visit(SyntaxTree::AssignStmt &node) + { + LOG("_assignstmt"); + // store + node.target->accept(*this); + auto tar_addr = left_val; + node.value->accept(*this); + auto rval = exp_val; + // 类型转换 + auto lval_type = tar_addr->get_type()->get_pointer_element_type(); + auto exp_type = rval->get_type(); + if (exp_type == INT1_T) // bool + { + rval = builder->create_zext(rval, INT32_T); + exp_type = INT32_T; + } + if (lval_type != exp_type) + { + if (lval_type == FLOAT_T) + { + rval = builder->create_sitofp(rval, FLOAT_T); + LOG("cast int to float"); + } + else + { + rval = builder->create_fptosi(rval, INT32_T); + LOG("cast float to int"); + } + } + builder->create_store(rval, tar_addr); + } -void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) {} + void IRBuilder::visit(SyntaxTree::Literal &node) + { + LOG("_literal"); + if (scope.in_global() || get_literal) + { + LOG("global or get_literal"); + if (node.literal_type == SyntaxTree::Type::INT) + { + LOG("literal type int"); + GlobalVar_.push_int(node.int_const); -void IRBuilder::visit(SyntaxTree::BinaryExpr &node) {} + LOG(GlobalVar_.get_size()); -void IRBuilder::visit(SyntaxTree::UnaryExpr &node) {} + // LOG(GlobalVar_.is_int()); -void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) {} + LOG("push int const: " << node.int_const); + } + else if (node.literal_type == SyntaxTree::Type::FLOAT) + { // 浮点数范围 + LOG("literal type float"); + GlobalVar_.push_float(float(node.float_const)); + } + } + else + { + if (node.literal_type == SyntaxTree::Type::INT) + { + exp_val = CONST_INT(node.int_const); + } + else if (node.literal_type == SyntaxTree::Type::FLOAT) + { + exp_val = CONST_FLOAT(float(node.float_const)); + } + } + LOG(" literal done"); + } -void IRBuilder::visit(SyntaxTree::IfStmt &node) {} + void IRBuilder::visit(SyntaxTree::ReturnStmt &node) + { + LOG("_returnstmt"); + auto retType = builder->get_insert_block()->get_parent()->get_return_type(); + if (retType->is_void_type()) + { // void + LOG("ret void"); + builder->create_br(ret_bb); + } + else if (node.ret == nullptr) // 函数非void,但表达式为空 + { // return 0 + LOG("ret 0"); + builder->create_store(CONST_INT(0), ret_addr); + builder->create_br(ret_bb); + } + else + { + // LOG( "here1" ); + node.ret->accept(*this); + // LOG( "here2" ); + exp_val->get_type(); + // LOG( "1" ); + if (exp_val->get_type() == INT1_T) // bool + { + LOG("return INT1_T"); + exp_val = builder->create_zext(exp_val, INT1_T); + } + if (exp_val->get_type() != retType) + { + if (retType == FLOAT_T) + { + LOG("ret cast int to float"); + auto ret_Val = builder->create_sitofp(exp_val, FLOAT_T); + builder->create_store(ret_Val, ret_addr); + builder->create_br(ret_bb); + } + else + { + LOG("ret cast float to int"); + auto ret_Val = builder->create_fptosi(exp_val, INT32_T); + builder->create_store(ret_Val, ret_addr); + builder->create_br(ret_bb); + } + } + else + { + LOG("ret normal"); + builder->create_store(exp_val, ret_addr); // return 4 的情况在这里处理 + builder->create_br(ret_bb); // 需要处理if_true_bb向main_ret的跳转(即if_true有return的情况) + } + } + } -void IRBuilder::visit(SyntaxTree::WhileStmt &node) {} + void IRBuilder::visit(SyntaxTree::BlockStmt &node) + { + LOG("_blockstmt"); + if (func_block == true) + { // 当前仍在函数开头处 + func_block = false; + } + else + { // 进入新的作用域 + scope.enter(); + LOG("enter"); + } + int cnt = 0; + for (auto blockstmt : node.body) + { + LOG("block:" << cnt++); + blockstmt->accept(*this); + LOG("block done"); + } -void IRBuilder::visit(SyntaxTree::BreakStmt &node) {} + scope.exit(); + LOG("exit"); + } -void IRBuilder::visit(SyntaxTree::ContinueStmt &node) {} + void IRBuilder::visit(SyntaxTree::EmptyStmt &node) + { + LOG("_emptystmt"); + // empty + } -} + void IRBuilder::visit(SyntaxTree::ExprStmt &node) + { + LOG("_exprstmt"); + node.exp->accept(*this); + } + + void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) + { + LOG("_unarycondexpr"); + if (scope.in_global() || get_literal) + { + node.rhs->accept(*this); + GlobalVar_.updateVal(node.op); + return; + } + node.rhs->accept(*this); + auto rhs = exp_val; + auto rhsType = rhs->get_type(); + if (rhsType == FLOAT_T) + { + exp_val = builder->create_fcmp_eq(rhs, CONST_FLOAT(0)); + } + else + { + if (rhsType == INT1_T) + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_eq(rhs, CONST_INT(0)); + } + } + + void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) + { + LOG("_binarycondexpr"); + if (scope.in_global() || get_literal) + { + node.lhs->accept(*this); + node.rhs->accept(*this); + GlobalVar_.updateVal(node.op); + return; + } + + node.lhs->accept(*this); + LOG("left oprand done"); + auto lhs = exp_val; + auto lhsType = lhs->get_type(); + node.rhs->accept(*this); + LOG("right oprand done"); + auto rhs = exp_val; + auto rhsType = rhs->get_type(); + switch (node.op) + { + case SyntaxTree::BinaryCondOp::EQ: + { + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_eq(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_eq(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_eq(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_eq(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_eq(lhs, rhs); + } + else + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_eq(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_eq(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_eq(lhs, rhs); + } + else + exp_val = builder->create_icmp_eq(lhs, rhs); + } + break; + } + case SyntaxTree::BinaryCondOp::NEQ: + { + LOG("bicon op neq"); + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_ne(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_ne(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_ne(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_ne(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_ne(lhs, rhs); + } + else + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_ne(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_ne(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_ne(lhs, rhs); + } + else + exp_val = builder->create_icmp_ne(lhs, rhs); + } + break; + } + case SyntaxTree::BinaryCondOp::GT: + { + LOG("bicond op gt"); + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_gt(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_gt(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_gt(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_gt(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_gt(lhs, rhs); + } + else // 两个操作数都是int + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + LOG("bicond op gt: lhs is int1, rhs is int32"); + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_gt(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + LOG("bicond op gt: lhs is int32, rhs is int1"); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_gt(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + LOG("bicond op gt: lhs is int1, rhs is int1"); + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_gt(lhs, rhs); + } + else + { + LOG("bicond op gt: lhs is int32, rhs is int32"); + exp_val = builder->create_icmp_gt(lhs, rhs); + } + } + break; + } + case SyntaxTree::BinaryCondOp::GTE: + { + LOG("bicond op gte"); + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_ge(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_ge(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_ge(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_ge(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_ge(lhs, rhs); + } + else + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_ge(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_ge(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_ge(lhs, rhs); + } + else + exp_val = builder->create_icmp_ge(lhs, rhs); + } + break; + } + case SyntaxTree::BinaryCondOp::LT: + { + LOG("bicond op lt"); + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_lt(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_lt(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_lt(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_lt(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_lt(lhs, rhs); + } + else + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_lt(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_lt(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_lt(lhs, rhs); + } + else + exp_val = builder->create_icmp_lt(lhs, rhs); + } + break; + } + case SyntaxTree::BinaryCondOp::LTE: + { + LOG("bicond op lte"); + if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType->is_integer_type()) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_le(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fcmp_le(lhs, rhs); + } + } + else if (rhsType->is_integer_type()) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_le(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fcmp_le(lhs, rhs); + } + } + else + exp_val = builder->create_fcmp_le(lhs, rhs); + } + else + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_icmp_le(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_le(lhs, rhs); + } + else if (lhsType == INT1_T && rhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_icmp_le(lhs, rhs); + } + else + exp_val = builder->create_icmp_le(lhs, rhs); + } + break; + } + case SyntaxTree::BinaryCondOp::LAND: + { + std::string name; + auto func_parent = now_func; + name = "next_land_bb_" + std::to_string(label_num++); + auto next_land_bb = BasicBlock::create(module, name, func_parent); + name = "after_land_bb_" + std::to_string(label_num++); + auto after_land_bb = BasicBlock::create(module, name, func_parent); + if (lhsType == INT1_T) + { + exp_val = lhs; + builder->create_cond_br(lhs, next_land_bb, after_land_bb); + } + else if (lhsType == INT32_T) + { + // LOG("land"); + auto cond_i1 = builder->create_icmp_ne(lhs, CONST_INT(0)); + exp_val = cond_i1; + builder->create_cond_br(cond_i1, next_land_bb, after_land_bb); + } + else if (lhsType == FLOAT_T) + { + auto cond_i1 = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); + exp_val = cond_i1; + builder->create_cond_br(cond_i1, next_land_bb, after_land_bb); + } + builder->set_insert_point(next_land_bb); + if (rhsType == INT1_T) + { + exp_val = rhs; + builder->create_br(after_land_bb); + } + else if (rhsType == INT32_T) + { + auto cond_i1 = builder->create_icmp_ne(rhs, CONST_INT(0)); + exp_val = cond_i1; + builder->create_br(after_land_bb); + } + else if (rhsType == FLOAT_T) + { + auto cond_i1 = builder->create_fcmp_ne(rhs, CONST_FLOAT(0)); + exp_val = cond_i1; + builder->create_br(after_land_bb); + } + builder->set_insert_point(after_land_bb); + break; + } + case SyntaxTree::BinaryCondOp::LOR: + { + std::string name; + auto func_parent = now_func; + name = "next_lor_bb_" + std::to_string(label_num++); + auto next_lor_bb = BasicBlock::create(module, name, func_parent); + name = "after_lor_bb_" + std::to_string(label_num++); + auto after_lor_bb = BasicBlock::create(module, name, func_parent); + if (lhsType == INT1_T) + { + exp_val = lhs; + builder->create_cond_br(lhs, after_lor_bb, next_lor_bb); + } + else if (lhsType == INT32_T) + { + auto cond_i1 = builder->create_icmp_ne(lhs, CONST_INT(0)); + exp_val = cond_i1; + builder->create_cond_br(cond_i1, after_lor_bb, next_lor_bb); + } + else if (lhsType == FLOAT_T) + { + auto cond_i1 = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); + exp_val = cond_i1; + builder->create_cond_br(cond_i1, after_lor_bb, next_lor_bb); + } + builder->set_insert_point(next_lor_bb); + if (rhsType == INT1_T) + { + exp_val = rhs; + builder->create_br(after_lor_bb); + } + else if (rhsType == INT32_T) + { + auto cond_i1 = builder->create_icmp_ne(exp_val, CONST_INT(0)); + exp_val = cond_i1; + builder->create_br(after_lor_bb); + } + else if (rhsType == FLOAT_T) + { + auto cond_i1 = builder->create_fcmp_ne(exp_val, CONST_FLOAT(0)); + exp_val = cond_i1; + builder->create_br(after_lor_bb); + } + builder->set_insert_point(after_lor_bb); + break; + } + } + LOG("binarycondexpr done"); + } + + void IRBuilder::visit(SyntaxTree::BinaryExpr &node) + { + LOG("_binaryexpr"); + if (scope.in_global() || get_literal) + { + node.lhs->accept(*this); + node.rhs->accept(*this); + GlobalVar_.updateVal(node.op); + return; + } + + node.lhs->accept(*this); + LOG("left oprand visited"); + Ptr lhs = exp_val; + LOG("lhs value"); + Ptr lhsType = lhs->get_type(); + LOG("lhs type"); + node.rhs->accept(*this); + LOG("right oprand visited"); + Ptr rhs = exp_val; + LOG("rhs value"); + Ptr rhsType = rhs->get_type(); + switch (node.op) + { + case SyntaxTree::BinOp::PLUS: + { + if (lhsType->is_integer_type() && rhsType->is_integer_type()) + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_iadd(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_iadd(lhs, rhs); + } + else + { + exp_val = builder->create_iadd(lhs, rhs); + } + } + else if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType != FLOAT_T) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fadd(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fadd(lhs, rhs); + } + } + else if (rhsType != FLOAT_T) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fadd(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fadd(lhs, rhs); + } + } + else + { + exp_val = builder->create_fadd(lhs, rhs); + } + } + else + { + PtrVec tmp; + tmp.clear(); + if (lhsType->is_pointer_type()) + { + tmp.push_back(rhs); + exp_val = builder->create_gep(lhs, tmp); + } + else + { + tmp.push_back(lhs); + exp_val = builder->create_gep(rhs, tmp); + } + } + break; + } + case SyntaxTree::BinOp::MINUS: + { + if (lhsType->is_integer_type() && rhsType->is_integer_type()) + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_isub(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_isub(lhs, rhs); + } + else + { + exp_val = builder->create_isub(lhs, rhs); + } + } + else if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType != FLOAT_T) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fsub(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fsub(lhs, rhs); + } + } + else if (rhsType != FLOAT_T) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fsub(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fsub(lhs, rhs); + } + } + else + { + exp_val = builder->create_fsub(lhs, rhs); + } + } + else + { + PtrVec tmp; + tmp.clear(); + rhs = builder->create_isub(CONST_INT(0), rhs); + tmp.push_back(rhs); + exp_val = builder->create_gep(lhs, tmp); + } + break; + } + case SyntaxTree::BinOp::MULTIPLY: + { + if (lhsType->is_integer_type() && rhsType->is_integer_type()) + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_imul(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_imul(lhs, rhs); + } + else + { + exp_val = builder->create_imul(lhs, rhs); + } + } + else if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType != FLOAT_T) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fmul(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fmul(lhs, rhs); + } + } + else if (rhsType != FLOAT_T) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fmul(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fmul(lhs, rhs); + } + } + else + { + exp_val = builder->create_fmul(lhs, rhs); + } + } + break; + } + case SyntaxTree::BinOp::DIVIDE: + { + if (lhsType->is_integer_type() && rhsType->is_integer_type()) + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_isdiv(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_isdiv(lhs, rhs); + } + else + { + exp_val = builder->create_isdiv(lhs, rhs); + } + } + else if (lhsType == FLOAT_T || rhsType == FLOAT_T) + { + if (lhsType != FLOAT_T) + { + if (lhsType == INT1_T) + { + lhs = builder->create_zext(lhs, INT32_T); + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fdiv(lhs, rhs); + } + else + { + lhs = builder->create_sitofp(lhs, FLOAT_T); + exp_val = builder->create_fdiv(lhs, rhs); + } + } + else if (rhsType != FLOAT_T) + { + if (rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fdiv(lhs, rhs); + } + else + { + rhs = builder->create_sitofp(rhs, FLOAT_T); + exp_val = builder->create_fdiv(lhs, rhs); + } + } + else + { + exp_val = builder->create_fdiv(lhs, rhs); + } + } + break; + } + case SyntaxTree::BinOp::MODULO: + { + if (lhsType == INT1_T && rhsType == INT32_T) + { + lhs = builder->create_zext(lhs, INT32_T); + exp_val = builder->create_isrem(lhs, rhs); + } + else if (lhsType == INT32_T && rhsType == INT1_T) + { + rhs = builder->create_zext(rhs, INT32_T); + exp_val = builder->create_isrem(lhs, rhs); + } + else + exp_val = builder->create_isrem(lhs, rhs); + break; + } + } + } + + void IRBuilder::visit(SyntaxTree::UnaryExpr &node) + { + LOG("_unaryexpr"); + if (scope.in_global() || get_literal) + { + node.rhs->accept(*this); + GlobalVar_.updateVal(node.op); + return; + } + node.rhs->accept(*this); + auto rhsType = exp_val->get_type(); + if (node.op == SyntaxTree::UnaryOp::MINUS) + { + if (rhsType == FLOAT_T) + { + exp_val = builder->create_fsub(CONST_FLOAT(0), exp_val); + } + else + { + if (rhsType == INT1_T) + { + exp_val = builder->create_zext(exp_val, INT32_T); + exp_val = builder->create_isub(CONST_INT(0), exp_val); + } + else + { + exp_val = builder->create_isub(CONST_INT(0), exp_val); + } + } + } + } + + void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) + { + LOG("_funccallstmt"); + auto func = dynamic_pointer_cast(scope.find(node.name, true)); + auto funcType = func->get_function_type(); + PtrVec params; + int num = 0; + for (auto param : node.params) + { + param->accept(*this); + auto value = exp_val; + auto Type = funcType->get_param_type(num++); + if (Type->is_array_type() || Type->is_pointer_type()) + { // pointer or array + params.push_back(value); + } + else if (Type != value->get_type()) + { + if (Type == INT32_T) + { + if (value->get_type() == INT1_T) + { + value = builder->create_zext(value, INT32_T); + params.push_back(value); + } + else + { // float + value = builder->create_fptosi(value, INT32_T); + params.push_back(value); + } + } + else + { // float + value = builder->create_sitofp(value, FLOAT_T); + params.push_back(value); + } + } + else + { + params.push_back(value); + } + } + exp_val = builder->create_call(func, params); + } + + void IRBuilder::visit(SyntaxTree::IfStmt &node) + { + LOG("_ifstmt"); + std::string name; + auto func_parent = now_func; + if (node.else_statement != nullptr) + { // 有else语句 + name = "true_if_" + std::to_string(label_num++); + auto true_if_bb = BasicBlock::create(module, name, func_parent); + name = "false_if_" + std::to_string(label_num++); + auto false_if_bb = BasicBlock::create(module, name, func_parent); + name = "after_if_" + std::to_string(label_num++); + auto after_if_bb = BasicBlock::create(module, name, func_parent); + node.cond_exp->accept(*this); + LOG("back to ifstmt"); + auto cond_exp_type = exp_val->get_type(); + if (cond_exp_type == INT1_T) + { + LOG("ifstmt: cond_exp is int1"); + // auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(exp_val, true_if_bb, false_if_bb); + } + else if (cond_exp_type == INT32_T) + { + LOG("ifstmt: cond_exp is int32"); + auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(cond, true_if_bb, false_if_bb); + } + else if (cond_exp_type == FLOAT_T) + { + LOG("ifstmt: cond_exp is float"); + auto cond = builder->create_fcmp_ne(exp_val, CONST_FLOAT(0)); + builder->create_cond_br(cond, true_if_bb, false_if_bb); + } + else + { + LOG("ifstmt: cond_exp is pointer"); + builder->create_br(true_if_bb); + } + builder->set_insert_point(true_if_bb); + node.if_statement->accept(*this); + if (!(builder->get_insert_block()->get_terminator())) + builder->create_br(after_if_bb); + builder->set_insert_point(false_if_bb); + node.else_statement->accept(*this); + if (!(builder->get_insert_block()->get_terminator())) + builder->create_br(after_if_bb); + builder->set_insert_point(after_if_bb); + } + else + { // 没有else语句 + name = "true_if_" + std::to_string(label_num++); + auto true_if_bb = BasicBlock::create(module, name, func_parent); + name = "after_if_" + std::to_string(label_num++); + auto after_if_bb = BasicBlock::create(module, name, func_parent); + node.cond_exp->accept(*this); + auto cond_exp_type = exp_val->get_type(); + // 条件判断语句计算结果的类型 + if (cond_exp_type == INT1_T) + { + LOG("ifstmt: cond_exp is int1"); + // auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(exp_val, true_if_bb, after_if_bb); + } + else if (cond_exp_type == INT32_T) + { + LOG("ifstmt: cond_exp is int32"); + auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(cond, true_if_bb, after_if_bb); + } + else if (cond_exp_type == FLOAT_T) + { + LOG("ifstmt: cond_exp is float"); + auto cond = builder->create_fcmp_ne(exp_val, CONST_FLOAT(0)); + builder->create_cond_br(cond, true_if_bb, after_if_bb); + } + else + { + LOG("ifstmt: cond_exp is pointer"); + builder->create_br(true_if_bb); + } + builder->set_insert_point(true_if_bb); + LOG("set insert point true_if_bb"); + node.if_statement->accept(*this); + LOG(builder->get_insert_block()->get_terminator()); + if ((builder->get_insert_block()->get_terminator()) == nullptr) + { + LOG("ifstmt: no terminator"); + builder->create_br(after_if_bb); + } + builder->set_insert_point(after_if_bb); + } + LOG("ifstmt done"); + } + + void IRBuilder::visit(SyntaxTree::WhileStmt &node) + { + LOG("_whilestmt"); + std::string name = "cond_while_" + std::to_string(label_num++); + auto func_parent = now_func; + auto cond_while_bb = BasicBlock::create(module, name, func_parent); + name = "while_" + std::to_string(label_num++); + auto while_bb = BasicBlock::create(module, name, func_parent); + name = "after_while_" + std::to_string(label_num++); + auto after_while_bb = BasicBlock::create(module, name, func_parent); + break_addr.push_back(after_while_bb); // break分支 + continue_addr.push_back(cond_while_bb); // continue分支 + builder->create_br(cond_while_bb); + builder->set_insert_point(cond_while_bb); + node.cond_exp->accept(*this); + auto cond_exp_type = exp_val->get_type(); + // cond_exp_type to INT1_T + if (cond_exp_type == INT1_T) + { + // auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(exp_val, while_bb, after_while_bb); + } + else if (cond_exp_type == INT32_T) + { + auto cond = builder->create_icmp_ne(exp_val, CONST_INT(0)); + builder->create_cond_br(cond, while_bb, after_while_bb); + } + else if (cond_exp_type == FLOAT_T) + { + auto cond = builder->create_fcmp_ne(exp_val, CONST_FLOAT(0)); + builder->create_cond_br(cond, while_bb, after_while_bb); + } + else + { + builder->create_br(while_bb); + } + + builder->set_insert_point(while_bb); + node.statement->accept(*this); + if (!(builder->get_insert_block()->get_terminator())) + builder->create_br(cond_while_bb); // 若没有终止语句,则跳转到循环条件 + + builder->set_insert_point(after_while_bb); // 循环后语句块 + + break_addr.pop_back(); + continue_addr.pop_back(); + } + + void IRBuilder::visit(SyntaxTree::BreakStmt &node) + { + LOG("_breakstmt"); + std::string name = "after_break_" + std::to_string(label_num++); + auto func_parent = now_func; + auto after_break_bb = BasicBlock::create(module, name, func_parent); + auto break_target = break_addr.back(); + builder->create_br(break_target); + builder->set_insert_point(after_break_bb); + } + + void IRBuilder::visit(SyntaxTree::ContinueStmt &node) + { + LOG("_continuestmt"); + std::string name = "after_continue_" + std::to_string(label_num++); + auto func_parent = now_func; + auto after_cont_bb = BasicBlock::create(module, name, func_parent); + auto cont_target = continue_addr.back(); + builder->create_br(cont_target); + builder->set_insert_point(after_cont_bb); + } + } } \ No newline at end of file