diff --git a/Student/task3/test/29_high_dim_array.out b/Student/task3/test/29_high_dim_array.out new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/Student/task3/test/29_high_dim_array.out @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/Student/task3/test/29_high_dim_array.sy b/Student/task3/test/29_high_dim_array.sy new file mode 100644 index 0000000..221aa03 --- /dev/null +++ b/Student/task3/test/29_high_dim_array.sy @@ -0,0 +1,7 @@ +int a[5][2] = {1,{2,3},{4},{5,6,7}}; +int b[5][2] = {{1,0},{2,3},{4,0},{5,6},{7,0}}; +int main(){ + int i = a[3][1]; + int j = b[3][1]; + return (i-j); +} diff --git a/Student/task3/test/30_high_dim_array_local.out b/Student/task3/test/30_high_dim_array_local.out new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/Student/task3/test/30_high_dim_array_local.out @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/Student/task3/test/30_high_dim_array_local.sy b/Student/task3/test/30_high_dim_array_local.sy new file mode 100644 index 0000000..d56cc4c --- /dev/null +++ b/Student/task3/test/30_high_dim_array_local.sy @@ -0,0 +1,7 @@ +int main(){ + int a[5][2] = {1,{2,3},{4},{5,6,7}}; + int b[5][2] = {{1,0},{2,3},{4,0},{5,6},{7,0}}; + int i = a[3][1]; + int j = b[3][1]; + return i - j; +} diff --git a/include/AST/SyntaxTree.h b/include/AST/SyntaxTree.h index 59bd387..a406bee 100755 --- a/include/AST/SyntaxTree.h +++ b/include/AST/SyntaxTree.h @@ -105,7 +105,6 @@ struct Node struct InitVal: Node{ bool isExp; PtrVec elementList; - //std::vector> elementList; Ptr expr; void accept(Visitor &visitor) final; }; diff --git a/include/SysYFIR/GlobalVariable.h b/include/SysYFIR/GlobalVariable.h index 7d251e1..c32423b 100644 --- a/include/SysYFIR/GlobalVariable.h +++ b/include/SysYFIR/GlobalVariable.h @@ -13,6 +13,8 @@ class GlobalVariable : public User { private: bool is_const_ ; + bool is_array_ ; + Ptr> array_dim_; Ptr init_val_; explicit GlobalVariable(std::string name, Ptr m, Ptr ty, bool is_const, Ptr init_val = nullptr); void init(std::string name, Ptr m, Ptr ty, bool is_const, Ptr init_val = nullptr); @@ -22,6 +24,15 @@ public: Ptr get_init() { return init_val_; } bool is_const() { return is_const_; } + bool is_array() { return is_array_; } + void set_array(Ptr> array_dim) { + is_array_ = true; + array_dim_ = array_dim; + } + Ptr> get_array_dim() { + if (is_array_) return array_dim_; + else return nullptr; + } std::string print(); }; diff --git a/include/SysYFIR/Instruction.h b/include/SysYFIR/Instruction.h index 9b4a420..e0b7d92 100644 --- a/include/SysYFIR/Instruction.h +++ b/include/SysYFIR/Instruction.h @@ -344,12 +344,22 @@ class AllocaInst : public Instruction private: explicit AllocaInst(Ptr ty, Ptr bb); void init(Ptr ty, Ptr bb); + bool is_array_ ; + Ptr> array_dim_; public: static Ptr create_alloca(Ptr ty, Ptr bb); Ptr get_alloca_type() const; - + bool is_array() { return is_array_; } + void set_array(Ptr> array_dim) { + is_array_ = true; + array_dim_ = array_dim; + } + Ptr> get_array_dim() { + if (is_array_) return array_dim_; + else return nullptr; + } virtual std::string print() override; private: diff --git a/include/SysYFIRBuilder/IRBuilder.h b/include/SysYFIRBuilder/IRBuilder.h index df85a94..322864b 100644 --- a/include/SysYFIRBuilder/IRBuilder.h +++ b/include/SysYFIRBuilder/IRBuilder.h @@ -75,6 +75,8 @@ private: class IRBuilder: public SyntaxTree::Visitor { private: + void ArrayInitTraverser(Ptr initVal, int depth, int index, Ptr varType, std::vector arrayDim); + void GetArrayInit(Ptr initVal, std::vector arrayDim, Ptr varType, bool global); void TypeConvert(Ptr origin, Ptr expected); void BinaryExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinOp op); void BinaryCondExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinaryCondOp op); diff --git a/src/SysYFIRBuilder/IRBuilder.cpp b/src/SysYFIRBuilder/IRBuilder.cpp index 02e913f..38f23d2 100644 --- a/src/SysYFIRBuilder/IRBuilder.cpp +++ b/src/SysYFIRBuilder/IRBuilder.cpp @@ -1,4 +1,3 @@ -#include #include "IRBuilder.h" namespace SysYF @@ -27,6 +26,8 @@ Ptr retBB; Ptr retAlloca; Ptr tmpInst; +Ptr arrayInitializer; +Ptr>> constArrayInit; // types @@ -37,6 +38,70 @@ Ptr FLOAT_T; Ptr INT32PTR_T; Ptr FLOATPTR_T; +void IRBuilder::ArrayInitTraverser(Ptr initVal, int depth, int index, Ptr varType, std::vector arrayDim) { + if(initVal->isExp) { + initVal->expr->accept(*this); + TypeConvert(tmpInst, varType); + //set constArrayInit[index] = tmpInst + constArrayInit->at(index) = dynamic_pointer_cast(tmpInst); + } else { + for (int i = 0; i < initVal->elementList.size(); i++) { + auto tmpIndex = 1; + for (int j = depth + 1; j < arrayDim.size(); j++) { + tmpIndex *= arrayDim[j]; + } + ArrayInitTraverser(initVal->elementList[i], depth + 1, index + i * tmpIndex, varType, arrayDim); + } + } +} + +void IRBuilder::GetArrayInit(Ptr initVal, std::vector arrayDim, Ptr varType, bool global = true) { + /* + arrayInitializer.reset(); + // 一维数组 + std::vector> varInit; + for(auto initValPtr : initVal->elementList){ + initValPtr->expr->accept(*this); + TypeConvert(tmpInst, varType); + varInit.push_back(dynamic_pointer_cast(tmpInst)); + } + auto arrayLen = arrayDim[0]; + auto otherLen = arrayLen - initVal->elementList.size(); + auto tmpZero = CONST_INT(0); + TypeConvert(tmpZero, varType); + for (auto i = 0u; i < otherLen; i++) { + varInit.push_back(dynamic_pointer_cast(tmpInst)); + } + auto arrayType = varType->get_array_type(varType, arrayLen); + arrayInitializer = ConstantArray::create(arrayType, varInit); + */ + auto arraySize = 1; + for(auto i : arrayDim){ + arraySize *= i; + } + constArrayInit = std::make_shared>>(arraySize); + ArrayInitTraverser(initVal, 0, 0, varType, arrayDim); + auto arrayType = varType->get_array_type(varType, arraySize); + //iterate constArrayInit to get arrayInitializer + std::vector> varInit; + for(auto i : *constArrayInit){ + if (i == nullptr) { + Ptr tmpZero; + if(varType == INT32_T){ + tmpZero = CONST_INT(0); + } else{ + tmpZero = CONST_FLOAT(0.0); + } + TypeConvert(tmpZero, varType); + varInit.push_back(dynamic_pointer_cast(tmpInst)); + } else { + varInit.push_back(i); + } + } + arrayInitializer = ConstantArray::create(arrayType, varInit); + +} + Ptr GetBaseType(SyntaxTree::Type type){ switch(type){ case SyntaxTree::Type::INT: @@ -62,6 +127,8 @@ Ptr GetParamType(SyntaxTree::Type type, bool isPtr = false){ else if(tmpType == FLOAT_T){ return FLOATPTR_T; } + else + return nullptr; } } @@ -107,8 +174,7 @@ void IRBuilder::BinaryExprGen(Ptr lhs, Ptr rhs, SyntaxTree::BinOp } break; case SyntaxTree::BinOp::MODULO: - if (isFloat) { ;// not support - } else { + if (!isFloat) { tmpInst = CONST_INT(lInt % rInt); } break; @@ -446,11 +512,23 @@ void IRBuilder::visit(SyntaxTree::FuncParam &node) { void IRBuilder::visit(SyntaxTree::VarDef &node) { // type auto varType = GetBaseType(node.btype); + std::vector arrayDim; Ptr arrayType; + int arraySize = 1; if (!node.array_length.empty()) { - node.array_length[0]->accept(*this); - auto constInt = dynamic_pointer_cast(tmpInst); - arrayType = ArrayType::create(varType, constInt->get_value()); + for (int i = node.array_length.size() - 1; i >= 0; i--) { + node.array_length[i]->accept(*this); + auto constInt = dynamic_pointer_cast(tmpInst); + if(i == node.array_length.size() - 1) { + arraySize = constInt->get_value(); + arrayDim.push_back(constInt->get_value()); + } else { + arraySize *= constInt->get_value(); + arrayDim.push_back(constInt->get_value()); + } + } + arrayType = ArrayType::create(varType, arraySize); + std::reverse(arrayDim.begin(), arrayDim.end()); } Ptr identAlloca; @@ -461,25 +539,21 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { identAlloca = GlobalVariable::create(node.name, module, varType, false, zeroInit); } else { identAlloca = GlobalVariable::create(node.name, module, arrayType, false, zeroInit); + // + auto tmpIdent = dynamic_pointer_cast(identAlloca); + tmpIdent->set_array(std::make_shared>(arrayDim)); + identAlloca = dynamic_pointer_cast(tmpIdent); + // } } else { if (!node.array_length.empty()) { - std::vector> varInit; - for (const auto &init : node.initializers->elementList) { - init->accept(*this); - TypeConvert(tmpInst, varType); - varInit.push_back(dynamic_pointer_cast(tmpInst)); - } - auto arrayLen = arrayType->get_num_of_elements(); - auto otherLen = arrayLen - node.initializers->elementList.size(); - auto tmpZero = CONST_INT(0); - TypeConvert(tmpZero, varType); - for (int i = 0; i < otherLen; i++) { - varInit.push_back(dynamic_pointer_cast(tmpInst)); - } - auto arrayInit = ConstantArray::create(varType->get_array_type(varType, arrayLen), varInit); - identAlloca = GlobalVariable::create(node.name, module, arrayType, node.is_constant, arrayInit); - + GetArrayInit(node.initializers, arrayDim, varType); + identAlloca = GlobalVariable::create(node.name, module, arrayType, node.is_constant, arrayInitializer); + // + auto tmpIdent = dynamic_pointer_cast(identAlloca); + tmpIdent->set_array(std::make_shared>(arrayDim)); + identAlloca = dynamic_pointer_cast(tmpIdent); + // } else { if (node.is_constant) { node.initializers->expr->accept(*this); @@ -501,7 +575,6 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { node.initializers->expr->accept(*this); TypeConvert(tmpInst, varType); scope.push(node.name, tmpInst); - //builder->create_store(tmpInst, identAlloca); } else { if (node.array_length.empty()) { identAlloca = builder->create_alloca(varType); @@ -513,25 +586,19 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { } return ; } else { - std::vector> varInit; - for (const auto &init : node.initializers->elementList) { - init->accept(*this); - TypeConvert(tmpInst, varType); - varInit.push_back(dynamic_pointer_cast(tmpInst)); - } - auto otherLen = arrayType->get_num_of_elements() - node.initializers->elementList.size(); - auto tmpZero = CONST_INT(0); - TypeConvert(tmpZero, varType); - for (int i = 0; i < otherLen; i++) { - varInit.push_back(dynamic_pointer_cast(tmpInst)); - } - auto zeroInit = ConstantZero::create(varType, module); + GetArrayInit(node.initializers, arrayDim, varType); + // identAlloca = builder->create_alloca(arrayType); + auto tmpIdent = dynamic_pointer_cast(identAlloca); + tmpIdent->set_array(std::make_shared>(arrayDim)); + // + identAlloca = dynamic_pointer_cast(tmpIdent); scope.push(node.name, identAlloca); - for (int i = 0; i < varInit.size(); i++) { + auto varInit = constArrayInit.get(); + for (int i = 0u; i < arraySize; i++) { auto index = CONST_INT(i); auto ptr = builder->create_gep(identAlloca, {CONST_INT(0), index}); - builder->create_store(varInit[i], ptr); + builder->create_store((*varInit)[i], ptr); } } } @@ -542,7 +609,8 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) { void IRBuilder::visit(SyntaxTree::LVal &node) { auto ident = scope.find(node.name, false); if (!node.array_index.empty()) { - node.array_index[0]->accept(*this); + + /*node.array_index[0]->accept(*this); auto constIndex = dynamic_pointer_cast(tmpInst); auto globalIdent = dynamic_pointer_cast(ident); if(globalIdent != nullptr && globalIdent->is_const() && constIndex != nullptr) { @@ -551,6 +619,37 @@ void IRBuilder::visit(SyntaxTree::LVal &node) { } else { tmpInst = builder->create_gep(ident, {CONST_INT(0), tmpInst}); } + */ + int index = 0; + auto globalIdent = dynamic_pointer_cast(ident); + auto localIdent = dynamic_pointer_cast(ident); + Ptr> arrayDimPtr; + if (globalIdent != nullptr) { + arrayDimPtr = globalIdent->get_array_dim(); + } else if (localIdent != nullptr) { + arrayDimPtr = localIdent->get_array_dim(); + } + bool index_is_constant = true; + for (int i = 0; i < node.array_index.size(); i++) { + node.array_index[i]->accept(*this); + auto constIndex = dynamic_pointer_cast(tmpInst); + if(constIndex == nullptr) { + index_is_constant = false; + } + int tmpIndex = 1; + for (int j = i + 1; j < node.array_index.size(); j++) { + tmpIndex *= (*arrayDimPtr)[j]; + } + index += constIndex->get_value() * tmpIndex; + } + if(globalIdent != nullptr && globalIdent->is_const() && index_is_constant) { + auto arrayInit = dynamic_pointer_cast(globalIdent->get_init()); + tmpInst = arrayInit->get_element_value(index); + } else { + tmpInst = builder->create_gep(ident, {CONST_INT(0), CONST_INT(index)}); + } + + } else { if (ident->get_type()->is_pointer_type() && ident->get_type()->get_pointer_element_type()->is_array_type()) { @@ -559,7 +658,6 @@ void IRBuilder::visit(SyntaxTree::LVal &node) { tmpInst = ident; } } - return ; } // FINISH @@ -599,7 +697,6 @@ void IRBuilder::visit(SyntaxTree::ReturnStmt &node) { } // every ret stmt only store the value and jump to the retBB builder->create_br(retBB); - return ; } // Finish @@ -611,18 +708,15 @@ void IRBuilder::visit(SyntaxTree::BlockStmt &node) { stmt->accept(*this); } scope.exit(); - return ; } // FINISH void IRBuilder::visit(SyntaxTree::EmptyStmt &node) { - return ; } // FINISH void IRBuilder::visit(SyntaxTree::ExprStmt &node) { node.exp->accept(*this); - return ; } // FINISH @@ -636,7 +730,6 @@ void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) { } else { tmpInst = CONST_INT((constInt->get_value() == 0 || constFloat->get_value() == 0 ) ? 1 : 0); } - return ; } @@ -790,19 +883,16 @@ void IRBuilder::visit(SyntaxTree::WhileStmt &node) { builder->set_insert_point(afterBB); curWhileBlock = tmpWhileBlock; - return ; } //FINISH void IRBuilder::visit(SyntaxTree::BreakStmt &node) { builder->create_br(curWhileBlock.afterBB); - return ; } //FINISH void IRBuilder::visit(SyntaxTree::ContinueStmt &node) { builder->create_br(curWhileBlock.condBB); - return ; } } } \ No newline at end of file