From d380bd01c1d109ff6db0ead0294836cfa69f06b9 Mon Sep 17 00:00:00 2001 From: pwue7rqmg <3279325045@qq.com> Date: Thu, 14 Dec 2023 01:22:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E9=AA=8C3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYFIRBuilder/IRBuilder.cpp | 1364 ++++++++++++++++++++++++++++++ 1 file changed, 1364 insertions(+) create mode 100644 src/SysYFIRBuilder/IRBuilder.cpp diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp new file mode 100644 index 0000000..984fed6 --- /dev/null +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -0,0 +1,1364 @@ +#include "IRBuilder.h" + +namespace SysYF +{ +namespace IR +{ +#define CONST_INT(num) ConstantInt::create(num, module) +#define CONST_FLOAT(num) ConstantFloat::create(num, module) + +std::list>> const_table; + +Ptr Lookup(std::string name) +{ + auto i = const_table.begin(); + for (; i != const_table.end(); i++) + { + auto iter = i->find(name); + if (iter != i->end()) + return iter->second; + } + return nullptr; +} + +PtrVec Params; +std::vector Param_names; +Ptr retAlloca = nullptr; +Ptr retBB = nullptr; +bool is_new_func = false; +bool get_const; +bool require_lval = false; +Ptr current_function = nullptr; +Ptr current_bb = nullptr; +Ptr recent_value = nullptr; +Ptr recent_ptr = nullptr; +Ptr nextBB_while = nullptr; +Ptr condBB_while = nullptr; +Ptr trueBB = nullptr; +Ptr falseBB = nullptr; +int id = 1; + +typedef struct InitItem +{ + bool isValue; + Ptr expr; + std::vector list; +} Inititem; +InitItem recentInitItem; + + +Ptr VOID_T; +Ptr INT1_T; +Ptr INT32_T; +Ptr FLOAT_T; +Ptr INT32PTR_T; +Ptr FLOATPTR_T; + +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 IR::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); + std::map> new_table; + const_table.push_front(new_table); + for (const auto &def : node.global_defs) + { + def->accept(*this); + } +} + +void IR::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 IR::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); + + + auto FunTy = FunctionType::create(ret_type, Params); + + auto Fun = Function::create(FunTy, node.name, module); + current_function = Fun; + scope.push(node.name, Fun); + + PtrVec args; + for (auto arg = Fun->arg_begin(); arg != Fun->arg_end(); arg++) + args.push_back(*arg); + + scope.enter(); + std::map> new_table; + const_table.push_front(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); + scope.push(Param_names[i], alloc); + } + retBB = BasicBlock::create(module, "ret", Fun); + if (ret_type == VOID_T) + { + 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); + + if (!current_bb->get_terminator()) + builder->create_br(retBB); +} + +void IR::IRBuilder::visit(SyntaxTree::FuncFParamList &node) +{ + for (auto param : node.params) + { + param->accept(*this); + } +} + +void IR::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); + Ptr target = aGep; + Ptr val = ConstantInt::create(0, module); + Ptr target_type; + if (dynamic_pointer_cast(target)) + { + target_type = (dynamic_pointer_cast(target))->get_type(); + target_type = (static_pointer_cast(target_type))->get_element_type(); + } + else + { + target_type = (static_pointer_cast(target))->get_alloca_type(); + } + if (val->get_type() == FLOAT_T && (target_type == INT32_T)) + { + auto tmp = builder->create_fptosi(val, INT32_T); + builder->create_store(tmp, target); + } + 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); + } + } + 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()) + { + 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); + } + } + } + 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) + { + Ptr target; + 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); + target = aGep; + } + else + { + target = alloca; + } + Ptr val = initVal.expr; + Ptr target_type; + if (dynamic_pointer_cast(target)) + { + target_type = (dynamic_pointer_cast(target))->get_type(); + target_type = (static_pointer_cast(target_type))->get_element_type(); + } + else + { + target_type = (static_pointer_cast(target))->get_alloca_type(); + } + if (val->get_type() == FLOAT_T && (target_type == INT32_T)) + { + auto tmp = builder->create_fptosi(val, INT32_T); + builder->create_store(tmp, target); + } + 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); + } + } + } + Ptr tmp = nullptr; + if (isConstant) + { + if (dynamic_pointer_cast(initVal.expr) && lValType == FLOAT_T) + { + int val = (dynamic_pointer_cast(initVal.expr))->get_value(); + tmp = ConstantFloat::create((float)val, module); + } + + 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; + } + } + } +} + + +void IR::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) + { + + 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)); + } + + else + global_alloca = GlobalVariable::create(name, module, lValType, node.is_constant, ConstantZero::create(lValType, module)); + + scope.push(name, global_alloca); + + if (node.is_constant) + const_table.front().insert(std::make_pair(name, global_alloca->get_init())); + } + + else + { + + auto alloca = builder->create_alloca(lValType); + scope.push(name, alloca); + if (node.is_inited) + { + + if (node.is_constant) + get_const = true; + node.initializers->accept(*this); + get_const = false; + + indexList.clear(); + indexMax.clear(); + depth = 0; + assignInitVal(alloca, lValType, node.is_constant, recentInitItem, builder, module, true); + if (node.is_constant) + { + const_table.front().insert(std::make_pair(name, parseConst(0, 0, lValType))); + } + } + } +} + +void IR::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 IR::IRBuilder::visit(SyntaxTree::AssignStmt &node) +{ + node.value->accept(*this); + auto val = recent_value; + + require_lval = true; + node.target->accept(*this); + auto target = recent_ptr; + Ptr target_type; + if (dynamic_pointer_cast(target)) + { + target_type = (dynamic_pointer_cast(target))->get_type(); + target_type = (static_pointer_cast(target_type))->get_element_type(); + } + else + { + target_type = (static_pointer_cast(target))->get_alloca_type(); + } + if (val->get_type() == FLOAT_T && (target_type == INT32_T)) + { + auto tmp = builder->create_fptosi(val, INT32_T); + builder->create_store(tmp, target); + } + 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); + } +} + + +void IR::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 IR::IRBuilder::visit(SyntaxTree::ReturnStmt &node) +{ + if (node.ret == NULL) + { + + recent_value = builder->create_br(retBB); + } + else + { + + 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 IR::IRBuilder::visit(SyntaxTree::BlockStmt &node) +{ + + if (is_new_func == true) + is_new_func = false; + + else + { + scope.enter(); + std::map> new_table; + const_table.push_front(new_table); + } + + + for (auto stmt : node.body) + { + stmt->accept(*this); + } + scope.exit(); + const_table.pop_front(); +} + +void IR::IRBuilder::visit(SyntaxTree::EmptyStmt &node) {} + +void IR::IRBuilder::visit(SyntaxTree::ExprStmt &node) +{ + node.exp->accept(*this); +} + +void IR::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; + falseBB = temp_t; + node.rhs->accept(*this); + auto rhs = recent_value; + + + if (rhs->get_type() == VOID_T) + return; + + 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; + } +} + +Ptr Cond_f(SyntaxTree::BinaryCondOp op, Ptr lhs, Ptr rhs, Ptr builder) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinaryCondOp::EQ: + value = builder->create_fcmp_eq(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::NEQ: + value = builder->create_fcmp_ne(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LT: + value = builder->create_fcmp_lt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LTE: + value = builder->create_fcmp_le(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GT: + value = builder->create_fcmp_gt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GTE: + value = builder->create_fcmp_ge(lhs, rhs); + break; + default: + break; + } + return value; +} + +Ptr Cond_i(SyntaxTree::BinaryCondOp op, Ptr lhs, Ptr rhs, Ptr builder) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinaryCondOp::EQ: + value = builder->create_icmp_eq(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::NEQ: + value = builder->create_icmp_ne(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LT: + value = builder->create_icmp_lt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::LTE: + value = builder->create_icmp_le(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GT: + value = builder->create_icmp_gt(lhs, rhs); + break; + case SyntaxTree::BinaryCondOp::GTE: + value = builder->create_icmp_ge(lhs, rhs); + break; + default: + break; + } + return value; +} + +void IR::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; + 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)); + + 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)); + 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; + 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)); + + 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)); + + 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; + 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); + 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); + 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) + { + //recent_value = Cond_i(op, lhs, rhs, builder); + 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 + { + //recent_value = Cond_f(op, lhs, rhs, builder); + 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; + } + } + } +} + +Ptr Bin_i(SyntaxTree::BinOp op, int ltmp, int rtmp, Ptr builder, Ptr module) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinOp::PLUS: + value = IR::ConstantInt::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + value = IR::ConstantInt::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + value = IR::ConstantInt::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + value = IR::ConstantInt::create(ltmp / rtmp, module); + break; + case SyntaxTree::BinOp::MODULO: + value = IR::ConstantInt::create(ltmp % rtmp, module); + break; + default: + break; + } + return value; +} + +Ptr Bin_f(SyntaxTree::BinOp op, int ltmp, int rtmp, Ptr builder, Ptr module) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinOp::PLUS: + value = IR::ConstantFloat::create(ltmp + rtmp, module); + break; + case SyntaxTree::BinOp::MINUS: + value = IR::ConstantFloat::create(ltmp - rtmp, module); + break; + case SyntaxTree::BinOp::MULTIPLY: + value = IR::ConstantFloat::create(ltmp * rtmp, module); + break; + case SyntaxTree::BinOp::DIVIDE: + value = IR::ConstantFloat::create(ltmp / rtmp, module); + break; + default: + break; + } + return value; +} + +Ptr Creat_bin_i(SyntaxTree::BinOp op, Ptr lhs, Ptr rhs, Ptr builder) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinOp::PLUS: + value = builder->create_iadd(lhs, rhs); + break; + case SyntaxTree::BinOp::MINUS: + value = builder->create_isub(lhs, rhs); + break; + case SyntaxTree::BinOp::MULTIPLY: + value = builder->create_imul(lhs, rhs); + break; + case SyntaxTree::BinOp::DIVIDE: + value = builder->create_isdiv(lhs, rhs); + break; + case SyntaxTree::BinOp::MODULO: + value = builder->create_isrem(lhs, rhs); + break; + default: + break; + } + return value; +} + +Ptr Creat_bin_f(SyntaxTree::BinOp op, Ptr lhs, Ptr rhs, Ptr builder) +{ + Ptr value; + switch (op) + { + case SyntaxTree::BinOp::PLUS: + value = builder->create_fadd(lhs, rhs); + break; + case SyntaxTree::BinOp::MINUS: + value = builder->create_fsub(lhs, rhs); + break; + case SyntaxTree::BinOp::MULTIPLY: + value = builder->create_fmul(lhs, rhs); + break; + case SyntaxTree::BinOp::DIVIDE: + value = builder->create_fdiv(lhs, rhs); + break; + default: + break; + } + return value; +} + +void IR::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; + + 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(); + //recent_value = Bin_i(op,ltmp,rtmp,builder,module); + 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(); + //recent_value = Bin_f(op,ltmp,rtmp,builder,module); + + 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(); + recent_value = Bin_f(op, ltmp, rtmp, builder, module); + + 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(); + recent_value = Bin_f(op, ltmp, rtmp, builder, module); + + 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 (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); + + 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); + + 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 (rhs->get_type() == INT32_T) + { + //recent_value = Creat_bin_i(op, lhs, rhs, builder); + + 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; + } + + } + + else + { + //recent_value = Creat_bin_f(op, lhs, rhs, builder); + + 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 IR::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 + { + 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 IR::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); + + 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); + } + + 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 IR::IRBuilder::visit(SyntaxTree::IfStmt &node) +{ + 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); + id_str = std::to_string(id++); + falseBB = BasicBlock::create(module, id_str, current_function); + 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); + + 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)); + + if (recent_value->get_type() != VOID_T) + builder->create_cond_br(recent_value, trueBB, falseBB); + + bool next = false; + + current_bb = trueBB; + builder->set_insert_point(trueBB); + node.if_statement->accept(*this); + if (!current_bb->get_terminator()) + { + next = true; + builder->create_br(nextBB_if); + } + + + 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; + builder->create_br(nextBB_if); + } + } + + if (!next && node.else_statement) + nextBB_if->erase_from_parent(); + else + { + current_bb = nextBB_if; + builder->set_insert_point(nextBB_if); + } + + trueBB = temp_t; + falseBB = temp_f; +} + +void IR::IRBuilder::visit(SyntaxTree::WhileStmt &node) +{ + + auto temp_condBB = condBB_while; + auto temp_trueBB = trueBB; + auto temp_falseBB = falseBB; + auto temp_nextBB_while = nextBB_while; + + std::string id_str; + id_str = std::to_string(id++); + condBB_while = BasicBlock::create(module, id_str, current_function); + id_str = std::to_string(id++); + trueBB = BasicBlock::create(module, id_str, current_function); + id_str = std::to_string(id++); + falseBB = BasicBlock::create(module, id_str, current_function); + nextBB_while = falseBB; + + builder->create_br(condBB_while); + current_bb = condBB_while; + builder->set_insert_point(condBB_while); + node.cond_exp->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)); + if (recent_value->get_type() != VOID_T) + builder->create_cond_br(recent_value, trueBB, falseBB); + + 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); + + condBB_while = temp_condBB; + trueBB = temp_trueBB; + falseBB = temp_falseBB; + nextBB_while = temp_nextBB_while; +} + +void IR::IRBuilder::visit(SyntaxTree::BreakStmt &node) +{ + recent_value = builder->create_br(nextBB_while); +} + +void IR::IRBuilder::visit(SyntaxTree::ContinueStmt &node) +{ + recent_value = builder->create_br(condBB_while); +} + +} +