diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp index 7ae2b07..0276fda 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -10,10 +10,14 @@ namespace IR // You can define global variables here // to store state -std::vector> funcParam; -int exprRes = 0; + // store temporary value Ptr tmp_val = nullptr; +std::vector> funcFParam; +int exprRes = 0; +std::string curFuncName = ""; +Ptr tmpInst; +bool isFloat = false; // types Ptr VOID_T; @@ -61,13 +65,13 @@ void IRBuilder::visit(SyntaxTree::InitVal &node) { void IRBuilder::visit(SyntaxTree::FuncDef &node) { node.param_list->accept(*this); - auto funcType = FunctionType::create(GetType(node.ret_type), funcParam); + auto funcType = FunctionType::create(GetType(node.ret_type), funcFParam); auto createFunc = Function::create(funcType, node.name, module); node.body->accept(*this); } void IRBuilder::visit(SyntaxTree::FuncFParamList &node) { - funcParam.clear(); + funcFParam.clear(); for (const auto ¶ : node.params) { para->accept(*this); } @@ -77,30 +81,30 @@ void IRBuilder::visit(SyntaxTree::FuncParam &node) { case SyntaxTree::Type::INT: if (!node.array_index.empty()) { // TODO: high dim array - funcParam.push_back(INT32PTR_T); + funcFParam.push_back(INT32PTR_T); } else - funcParam.push_back(INT32_T); + funcFParam.push_back(INT32_T); break; case SyntaxTree::Type::FLOAT: if (!node.array_index.empty()) { // TODO: high dim array - funcParam.push_back(FLOATPTR_T); + funcFParam.push_back(FLOATPTR_T); } else - funcParam.push_back(FLOAT_T); + funcFParam.push_back(FLOAT_T); break; case SyntaxTree::Type::VOID: - funcParam.push_back(VOID_T); + funcFParam.push_back(VOID_T); break; case SyntaxTree::Type::STRING: - funcParam.push_back(INT32PTR_T); + funcFParam.push_back(INT32PTR_T); break; case SyntaxTree::Type::BOOL: - funcParam.push_back(INT1_T); + funcFParam.push_back(INT1_T); break; default: - funcParam.push_back(INT32_T); + funcFParam.push_back(INT32_T); break; } } @@ -110,47 +114,207 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { } void IRBuilder::visit(SyntaxTree::LVal &node) { - + auto ident = scope.find(node.name, false); + if (!node.array_index.empty()) { + //TODO: high dim array + node.array_index[0]->accept(*this); + auto index = tmpInst; + tmpInst = builder->create_gep(ident, {CONST_INT(0), index}); + } + else { + tmpInst = dynamic_pointer_cast(ident); + } } void IRBuilder::visit(SyntaxTree::AssignStmt &node) { - + node.target->accept(*this); + auto target = tmpInst; + node.value->accept(*this); + auto value = tmpInst; + builder->create_store(value, target); } void IRBuilder::visit(SyntaxTree::Literal &node) { - + /* + switch(node.literal_type) { + case SyntaxTree::Type::INT: + tmp_val = CONST_INT(node.int_val); + break; + case SyntaxTree::Type::FLOAT: + tmp_val = CONST_FLOAT(node.float_val); + break; + case SyntaxTree::Type::BOOL: + tmp_val = CONST_INT(node.bool_val); + break; + case SyntaxTree::Type::STRING: + tmp_val = CONST_INT(node.str_val); + break; + default: + tmp_val = CONST_INT(0); + break; + } + */ } void IRBuilder::visit(SyntaxTree::ReturnStmt &node) { - + node.ret->accept(*this); + builder->create_ret(tmpInst); + return ; } void IRBuilder::visit(SyntaxTree::BlockStmt &node) { - + for (const auto &stmt : node.body) { + stmt->accept(*this); + } + return ; } void IRBuilder::visit(SyntaxTree::EmptyStmt &node) { - + return ; } void IRBuilder::visit(SyntaxTree::ExprStmt &node) { - + node.exp->accept(*this); + return ; } void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) { - + node.rhs->accept(*this); + switch (node.op) { + case SyntaxTree::UnaryCondOp::NOT: + if(isFloat){ + tmpInst = builder->create_fcmp_eq(tmpInst, CONST_FLOAT(0.0)); + } + else + tmpInst = builder->create_icmp_eq(tmpInst, CONST_INT(0)); + default: + break; + } } void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) { - + node.lhs->accept(*this); + auto lhs = tmpInst; + node.rhs->accept(*this); + auto rhs = tmpInst; + switch (node.op) { + case SyntaxTree::BinaryCondOp::LT: + if (isFloat) { + tmpInst = builder->create_fcmp_lt(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_gt(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::LTE: + if (isFloat) { + tmpInst = builder->create_fcmp_le(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_le(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::GT: + if (isFloat) { + tmpInst = builder->create_fcmp_gt(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_gt(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::GTE: + if (isFloat) { + tmpInst = builder->create_fcmp_ge(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_ge(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::EQ: + if (isFloat) { + tmpInst = builder->create_fcmp_eq(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_eq(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::NEQ: + if (isFloat) { + tmpInst = builder->create_fcmp_ne(lhs, rhs); + } + else { + tmpInst = builder->create_icmp_ne(lhs, rhs); + } + break; + case SyntaxTree::BinaryCondOp::LAND: + //TODO: and + break; + case SyntaxTree::BinaryCondOp::LOR: + //TODO: or + break; + } } void IRBuilder::visit(SyntaxTree::BinaryExpr &node) { + node.lhs->accept(*this); + auto lhs = tmpInst; + node.rhs->accept(*this); + auto rhs = tmpInst; + switch (node.op) { + case SyntaxTree::BinOp::PLUS: + if(isFloat){ + tmpInst = builder->create_fadd(lhs, rhs); + } + else + tmpInst = builder->create_iadd(lhs, rhs); + break; + case SyntaxTree::BinOp::MINUS: + if(isFloat){ + tmpInst = builder->create_fsub(lhs, rhs); + } + else + tmpInst = builder->create_isub(lhs, rhs); + break; + case SyntaxTree::BinOp::MULTIPLY: + if(isFloat){ + tmpInst = builder->create_fmul(lhs, rhs); + } + else + tmpInst = builder->create_imul(lhs, rhs); + break; + case SyntaxTree::BinOp::DIVIDE: + if(isFloat){ + tmpInst = builder->create_fdiv(lhs, rhs); + } else { + tmpInst = builder->create_isdiv(lhs, rhs); + } + break; + case SyntaxTree::BinOp::MODULO: + if(isFloat){ + // not support + } else { + tmpInst = builder->create_isrem(lhs, rhs); + } + break; + } } void IRBuilder::visit(SyntaxTree::UnaryExpr &node) { - + node.rhs->accept(*this); + switch (node.op) { + case SyntaxTree::UnaryOp::PLUS: + break; + case SyntaxTree::UnaryOp::MINUS: + if(isFloat){ + tmpInst = builder->create_fsub(CONST_FLOAT(0.0), tmpInst); + } + else + tmpInst = builder->create_isub(CONST_INT(0), tmpInst); + break; + default: + break; + } } void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) { @@ -158,11 +322,37 @@ void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) { } void IRBuilder::visit(SyntaxTree::IfStmt &node) { - + auto curFunc = dynamic_pointer_cast(scope.find(curFuncName, true)); + node.cond_exp->accept(*this); + auto cond = tmp_val; + auto trueBB = BasicBlock::create(module, "trueBB_if", curFunc); + auto falseBB = BasicBlock::create(module, "falseBB_if", curFunc); + builder->create_cond_br(cond, trueBB, falseBB); + builder->set_insert_point(trueBB); + node.if_statement->accept(*this); + builder->set_insert_point(falseBB); + node.else_statement->accept(*this); } void IRBuilder::visit(SyntaxTree::WhileStmt &node) { + auto curFunc = dynamic_pointer_cast(scope.find(curFuncName, true)); + auto condBB = BasicBlock::create(module, "condBB_while", curFunc); + auto bodyBB = BasicBlock::create(module, "bodyBB_while", curFunc); + auto afterBB = BasicBlock::create(module, "afterBB_while", curFunc); + + builder->create_br(condBB); + + builder->set_insert_point(condBB); + node.cond_exp->accept(*this); + auto cond = tmp_val; + + builder->create_cond_br(cond, bodyBB, afterBB); + + builder->set_insert_point(bodyBB); + node.statement->accept(*this); + builder->create_br(condBB); + builder->set_insert_point(afterBB); } void IRBuilder::visit(SyntaxTree::BreakStmt &node) {