From 6102b29494bd31bf4dffe637a73285892b04d4f8 Mon Sep 17 00:00:00 2001 From: Odeinjul Date: Thu, 14 Dec 2023 15:28:57 +0800 Subject: [PATCH] Modified something --- include/SysYFIRBuilder/IRBuilder.h | 1 + src/SysYFIRBuilder/IRBuilder.cpp | 239 ++++++++++++++++++++++------- src/main.cpp | 2 + 3 files changed, 188 insertions(+), 54 deletions(-) diff --git a/include/SysYFIRBuilder/IRBuilder.h b/include/SysYFIRBuilder/IRBuilder.h index bb59091..ce1c88b 100644 --- a/include/SysYFIRBuilder/IRBuilder.h +++ b/include/SysYFIRBuilder/IRBuilder.h @@ -75,6 +75,7 @@ private: class IRBuilder: public SyntaxTree::Visitor { private: + void TypeConvert(Ptr origin, Ptr expected); 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 0152bd6..f5c1b62 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -13,12 +13,32 @@ namespace IR // to store state // store temporary value + +std::vector> funcFParam; + +struct WhileBlock { + BasicBlock *condBB; + BasicBlock *innerBB; + BasicBlock *exitBB; +}; +auto curWhileBlock = WhileBlock{nullptr, nullptr, nullptr}; + +struct CondBlock { + BasicBlock *trueBB; + BasicBlock *falseBB; +}; +auto curCondStruct = CondBlock{nullptr, nullptr}; + +Ptr retBB; +Ptr retAlloca; + +Ptr tmpInst; + + int tmpConstVal = 0; Ptr tmpVal = nullptr; -std::vector> funcFParam; std::vector> arrayInitializer; std::string curFuncName = ""; -Ptr tmpInst; bool isFloat = false; bool isAddr = false; Ptr curCondBB; @@ -32,12 +52,12 @@ Ptr FLOAT_T; Ptr INT32PTR_T; Ptr FLOATPTR_T; -Ptr GetType(SyntaxTree::Type type){ +Ptr GetBaseType(SyntaxTree::Type type){ switch(type){ case SyntaxTree::Type::INT: return INT32_T; case SyntaxTree::Type::FLOAT: - return INT1_T; + return FLOAT_T; case SyntaxTree::Type::VOID: return VOID_T; default: @@ -45,6 +65,62 @@ Ptr GetType(SyntaxTree::Type type){ } } +Ptr GetParamType(SyntaxTree::Type type, bool isPtr = false){ + auto tmpType = GetBaseType(type); + if(!isPtr || tmpType == nullptr || tmpType == VOID_T){ + return tmpType; + } + else { + if(tmpType == INT32_T){ + return INT32PTR_T; + } + else if(tmpType == FLOAT_T){ + return FLOATPTR_T; + } + } +} + +void IRBuilder::TypeConvert(Ptr origin, Ptr expected) { + if (dynamic_pointer_cast(origin) == nullptr) { + auto type = origin->get_type(); + if (type == expected) { + return; + } + if (type->is_pointer_type()) { + type = type->get_pointer_element_type(); + origin = builder->create_load(origin); + } + + if (type == INT32_T && expected == FLOAT_T) { + origin = builder->create_sitofp(origin, expected); + return; + } + if (type == FLOAT_T && expected == INT32_T) { + origin = builder->create_fptosi(origin, expected); + return; + } + } else { + auto tmpInt = dynamic_pointer_cast(origin); + auto tmpFloat = dynamic_pointer_cast(origin); + if (tmpInt != nullptr) { + if (expected == FLOAT_T) + tmpInst = CONST_FLOAT(tmpInt->get_value()); + else if (expected == INT1_T) + tmpInst = CONST_INT(tmpInt->get_value() != 0); + } + if (tmpFloat != nullptr) { + if (expected == INT32_T) + tmpInst = + CONST_INT(static_cast(tmpInt->get_value())); + else if (expected == INT1_T) + tmpInst = CONST_INT(tmpFloat->get_value() != 0); + } + return; + } + +} + + void IRBuilder::visit(SyntaxTree::Assembly &node) { VOID_T = Type::get_void_type(module); @@ -54,53 +130,86 @@ void IRBuilder::visit(SyntaxTree::Assembly &node) { INT32PTR_T = Type::get_int32_ptr_type(module); FLOATPTR_T = Type::get_float_ptr_type(module); for (const auto &def : node.global_defs) { + //std::cout << "4" << std::endl; def->accept(*this); } } // You need to fill them +// TODO void IRBuilder::visit(SyntaxTree::InitVal &node) { - + node.expr->accept(*this); } +// FINISH void IRBuilder::visit(SyntaxTree::FuncDef &node) { + auto funcRetType = GetParamType(node.ret_type); node.param_list->accept(*this); - auto funcType = FunctionType::create(GetType(node.ret_type), funcFParam); - auto createFunc = Function::create(funcType, node.name, module); + auto funcType = FunctionType::create(funcRetType, funcFParam); + auto func = Function::create(funcType, node.name, module); + scope.push(node.name, func); + + scope.enter(); + auto entryBlock = BasicBlock::create(module, "funcEntry", func); + retBB = BasicBlock::create(module, "ret", func); + + builder->set_insert_point(entryBlock); + + auto para = node.param_list->params.begin(); + for (auto arg = func->arg_begin(); arg != func->arg_end() ; arg++) { + auto name = (*para)->name; + auto val = (*arg); + auto argAlloca = builder->create_alloca(val->get_type()); + builder->create_store(val, argAlloca); + scope.push(name, argAlloca); + para++; + } + + if (funcRetType == VOID_T) { + ; + } else { + retAlloca = builder->create_alloca(funcRetType); + } + node.body->accept(*this); + + if (builder->get_insert_block()->get_terminator() == nullptr) { + if (funcRetType == INT32_T) { + builder->create_store(CONST_INT(0), retAlloca); + } else if (funcRetType == FLOAT_T) { + builder->create_store(CONST_FLOAT(0), retAlloca); + } + builder->create_br(retBB); + } + + builder->set_insert_point(retBB); + if (funcRetType == VOID_T) { + builder->create_void_ret(); + } else { + auto ret_val = builder->create_load(retAlloca); + builder->create_ret(ret_val); + } + + scope.exit(); } +// FINISH void IRBuilder::visit(SyntaxTree::FuncFParamList &node) { funcFParam.clear(); for (const auto ¶ : node.params) { para->accept(*this); } } + +// FINISH void IRBuilder::visit(SyntaxTree::FuncParam &node) { - switch(node.param_type) { - case SyntaxTree::Type::INT: - if (!node.array_index.empty()) { - // TODO: high dim array - funcFParam.push_back(INT32PTR_T); - } else { - funcFParam.push_back(INT32_T); - } - break; - case SyntaxTree::Type::FLOAT: - if (!node.array_index.empty()) { - // TODO: high dim array (not now) - funcFParam.push_back(FLOATPTR_T); - } else { - funcFParam.push_back(FLOAT_T); - } - break; - default: - funcFParam.push_back(INT32_T); - break; - } + auto tmpType = GetParamType(node.param_type, node.array_index[0] != nullptr); + funcFParam.push_back(tmpType); } + +// TODO void IRBuilder::visit(SyntaxTree::VarDef &node) { // TODO: high dim array (not now) int arrayLength; @@ -233,43 +342,42 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { } +// TODO void IRBuilder::visit(SyntaxTree::LVal &node) { auto ident = scope.find(node.name, false); + if (!node.array_index.empty()) { - //TODO: high dim array (not now) - node.array_index[0]->accept(*this); - auto index = tmpInst; - tmpInst = builder->create_gep(ident, {CONST_INT(0), index}); + //TODO } else { - tmpInst = dynamic_pointer_cast(ident); + if (ident->get_type()->is_pointer_type() && ident->get_type()->get_pointer_element_type()->is_array_type()) { + tmpInst = builder->create_gep(ident, {CONST_INT(0), CONST_INT(0)}); + } else { + tmpInst = ident; + } } isAddr = true; } +// FINISH void IRBuilder::visit(SyntaxTree::AssignStmt &node) { node.target->accept(*this); auto target = tmpInst; node.value->accept(*this); - Ptr value; - if (isAddr) { - value = builder->create_load(tmpInst); - isAddr = false; - } - else - value = dynamic_pointer_cast(tmpInst); + auto value = tmpInst; + TypeConvert(value, target->get_type()); + value = tmpInst; builder->create_store(value, target); } +//FINISH void IRBuilder::visit(SyntaxTree::Literal &node) { switch(node.literal_type) { case SyntaxTree::Type::INT: tmpVal = CONST_INT(node.int_const); - isFloat = false; break; case SyntaxTree::Type::FLOAT: tmpVal = CONST_FLOAT(node.float_const); - isFloat = true; break; default: tmpVal = CONST_INT(0); @@ -277,44 +385,60 @@ void IRBuilder::visit(SyntaxTree::Literal &node) { } } +// Finish void IRBuilder::visit(SyntaxTree::ReturnStmt &node) { - node.ret->accept(*this); - builder->create_ret(tmpVal); + if (node.ret) { + node.ret->accept(*this); + auto expectRetType = + builder->get_insert_block()->get_parent()->get_return_type(); + TypeConvert(tmpInst, expectRetType); + auto retValue = tmpInst; + builder->create_store(retValue, retAlloca); + } + // every ret stmt only store the value and jump to the retBB + builder->create_br(retBB); + return ; } +// Finish void IRBuilder::visit(SyntaxTree::BlockStmt &node) { scope.enter(); for (const auto &stmt : node.body) { stmt->accept(*this); + if (builder->get_insert_block()->get_terminator() != nullptr) + break; } scope.exit(); return ; } +// FINISH void IRBuilder::visit(SyntaxTree::EmptyStmt &node) { return ; } +// FINISH void IRBuilder::visit(SyntaxTree::ExprStmt &node) { node.exp->accept(*this); return ; } +// FINISH 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; + TypeConvert(tmpInst, INT32_T); + auto constInt = dynamic_pointer_cast(tmpInst); + auto constFloat = dynamic_pointer_cast(tmpInst); + if (constInt == nullptr && constFloat == nullptr) { + tmpInst = builder->create_icmp_eq(tmpInst, CONST_INT(0)); + } else { + tmpInst = CONST_INT((constInt->get_value() == 0 || constFloat->get_value() == 0 ) ? 1 : 0); } + return ; } + +// TODO void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) { auto curFunc = builder->get_insert_block()->get_parent(); auto trueBB = BasicBlock::create(module, "trueBB_and", curFunc); @@ -412,6 +536,7 @@ void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) { } } +// TODO void IRBuilder::visit(SyntaxTree::BinaryExpr &node) { node.lhs->accept(*this); auto lhs = tmpInst; @@ -465,6 +590,7 @@ void IRBuilder::visit(SyntaxTree::BinaryExpr &node) { } +// TODO void IRBuilder::visit(SyntaxTree::UnaryExpr &node) { node.rhs->accept(*this); switch (node.op) { @@ -482,6 +608,7 @@ void IRBuilder::visit(SyntaxTree::UnaryExpr &node) { } } +// TODO void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) { auto curFunc = builder->get_insert_block()->get_parent(); std::vector> funcRParam; @@ -492,6 +619,7 @@ void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) { builder->create_call(curFunc, funcRParam); } +// TODO void IRBuilder::visit(SyntaxTree::IfStmt &node) { auto curFunc = builder->get_insert_block()->get_parent(); node.cond_exp->accept(*this); @@ -505,6 +633,7 @@ void IRBuilder::visit(SyntaxTree::IfStmt &node) { node.else_statement->accept(*this); } +// TODO void IRBuilder::visit(SyntaxTree::WhileStmt &node) { auto curFunc = builder->get_insert_block()->get_parent(); auto condBB = BasicBlock::create(module, "condBB_while", curFunc); @@ -530,11 +659,13 @@ void IRBuilder::visit(SyntaxTree::WhileStmt &node) { return ; } +// TODO void IRBuilder::visit(SyntaxTree::BreakStmt &node) { builder->create_br(curAfterBB); return ; } +// TODO void IRBuilder::visit(SyntaxTree::ContinueStmt &node) { builder->create_br(curCondBB); return ; diff --git a/src/main.cpp b/src/main.cpp index cae2b75..a4232bd 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,8 +44,10 @@ int main(int argc, char *argv[]) } } auto root = driver.parse(filename); + std::cout << "AST start." << std::endl; if (print_ast) root->accept(printer); + std::cout << "IR start." << std::endl; if (print_ir) { root->accept(*builder); auto m = builder->getModule();