diff --git a/include/SysYFIRBuilder/IRBuilder.h b/include/SysYFIRBuilder/IRBuilder.h index ce1c88b..df85a94 100644 --- a/include/SysYFIRBuilder/IRBuilder.h +++ b/include/SysYFIRBuilder/IRBuilder.h @@ -76,6 +76,8 @@ class IRBuilder: public SyntaxTree::Visitor { private: void TypeConvert(Ptr origin, Ptr expected); + void BinaryExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinOp op); + void BinaryCondExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinaryCondOp op); virtual void visit(SyntaxTree::InitVal &) override final; virtual void visit(SyntaxTree::Assembly &) override final; virtual void visit(SyntaxTree::FuncDef &) override final; diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp index b4a3ab2..093a320 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -74,6 +74,244 @@ Ptr GetParamType(SyntaxTree::Type type, bool isPtr = false){ } } +void IRBuilder::BinaryExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinOp op){ + bool isFloat = false; + int lInt, rInt; + float lFloat, rFloat; + if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) { + if (dynamic_pointer_cast(lhs) || dynamic_pointer_cast(rhs)) { + isFloat = true; + lFloat = dynamic_pointer_cast(lhs)->get_value(); + rFloat = dynamic_pointer_cast(rhs)->get_value(); + } + else { + isFloat = false; + lInt = dynamic_pointer_cast(lhs)->get_value(); + rInt = dynamic_pointer_cast(rhs)->get_value(); + } + switch (op) { + case SyntaxTree::BinOp::PLUS: + if (isFloat) { + tmpInst = CONST_FLOAT(lFloat + rFloat); + } else + tmpInst = CONST_INT(lInt + rInt); + break; + case SyntaxTree::BinOp::MINUS: + if (isFloat) { + tmpInst = CONST_FLOAT(lFloat - rFloat); + } else + tmpInst = CONST_INT(lInt - rInt); + break; + case SyntaxTree::BinOp::MULTIPLY: + if (isFloat) { + tmpInst = CONST_FLOAT(lFloat * rFloat); + } else + tmpInst = CONST_INT(lInt * rInt); + break; + case SyntaxTree::BinOp::DIVIDE: + if (isFloat) { + tmpInst = CONST_FLOAT(lFloat / rFloat); + } else { + tmpInst = CONST_INT(lInt / rInt); + } + break; + case SyntaxTree::BinOp::MODULO: + if (isFloat) { ;// not support + } else { + tmpInst = CONST_INT(lInt % rInt); + } + break; + } + } else { + if (lhs->get_type()->is_pointer_type()) { + lhs = builder->create_load(lhs); + } + if (rhs->get_type()->is_pointer_type()) { + rhs = builder->create_load(rhs); + } + if (lhs->get_type()->is_float_type() && + rhs->get_type()->is_integer_type()) { + rhs = builder->create_sitofp(rhs, FLOAT_T); + } + if (lhs->get_type()->is_integer_type() && + rhs->get_type()->is_float_type()) { + lhs = builder->create_sitofp(lhs, FLOAT_T); + } + isFloat = lhs->get_type()->is_float_type(); + switch (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::BinaryCondExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinaryCondOp op) { + bool isFloat = false; + int lInt, rInt; + float lFloat, rFloat; + if (dynamic_pointer_cast(lhs) && dynamic_pointer_cast(rhs)) { + if (dynamic_pointer_cast(lhs) || dynamic_pointer_cast(rhs)) { + isFloat = true; + lFloat = dynamic_pointer_cast(lhs)->get_value(); + rFloat = dynamic_pointer_cast(rhs)->get_value(); + } + else { + isFloat = false; + lInt = dynamic_pointer_cast(lhs)->get_value(); + rInt = dynamic_pointer_cast(rhs)->get_value(); + } + switch (op) { + case SyntaxTree::BinaryCondOp::LT: + if (isFloat) { + tmpInst = CONST_INT(lFloat < rFloat); + } + else { + tmpInst = CONST_INT(lInt < rInt); + } + break; + case SyntaxTree::BinaryCondOp::LTE: + if (isFloat) { + tmpInst = CONST_INT(lFloat <= rFloat); + } + else { + tmpInst = CONST_INT(lInt <= rInt); + } + break; + case SyntaxTree::BinaryCondOp::GT: + if (isFloat) { + tmpInst = CONST_INT(lFloat > rFloat); + } + else { + tmpInst = CONST_INT(lInt > rInt); + } + break; + case SyntaxTree::BinaryCondOp::GTE: + if (isFloat) { + tmpInst = CONST_INT(lFloat >= rFloat); + } + else { + tmpInst = CONST_INT(lInt >= rInt); + } + break; + case SyntaxTree::BinaryCondOp::EQ: + if (isFloat) { + tmpInst = CONST_INT(lFloat == rFloat); + } + else { + tmpInst = CONST_INT(lInt == rInt); + } + break; + case SyntaxTree::BinaryCondOp::NEQ: + if (isFloat) { + tmpInst = CONST_INT(lFloat != rFloat); + } + else { + tmpInst = CONST_INT(lInt != rInt); + } + break; + default: + break; + } + } else { + if (lhs->get_type()->is_pointer_type()) { + lhs = builder->create_load(lhs); + } + if (rhs->get_type()->is_pointer_type()) { + rhs = builder->create_load(rhs); + } + if (lhs->get_type()->is_float_type() && + rhs->get_type()->is_integer_type()) { + rhs = builder->create_sitofp(rhs, FLOAT_T); + } + if (lhs->get_type()->is_integer_type() && + rhs->get_type()->is_float_type()) { + lhs = builder->create_sitofp(lhs, FLOAT_T); + } + isFloat = lhs->get_type()->is_float_type(); + switch (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; + default: + break; + } + } +} + void IRBuilder::TypeConvert(Ptr origin, Ptr expected) { if (dynamic_pointer_cast(origin) == nullptr) { auto type = origin->get_type(); @@ -121,7 +359,6 @@ void IRBuilder::TypeConvert(Ptr origin, Ptr expected) { } return; } - } @@ -549,58 +786,13 @@ void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) { } } -// TODO +// FINISH void IRBuilder::visit(SyntaxTree::BinaryExpr &node) { node.lhs->accept(*this); auto lhs = tmpInst; - if (isAddr) { - lhs = builder->create_load(lhs); - isAddr = false; - } node.rhs->accept(*this); auto rhs = tmpInst; - if(isAddr){ - rhs = builder->create_load(rhs); - isAddr = false; - } - 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; - } - + BinaryExprGen(lhs, rhs, node.op); } // FINISH @@ -617,7 +809,7 @@ void IRBuilder::visit(SyntaxTree::UnaryExpr &node) { } else if (constFloat != nullptr) { tmpInst = CONST_FLOAT(-constFloat->get_value()); } else { - //TODO; + BinaryExprGen(CONST_INT(0), tmpInst, SyntaxTree::BinOp::MINUS); } break; default: