From: Lauro Ramos Venancio Date: Mon, 18 Feb 2008 22:44:02 +0000 (+0000) Subject: Implement multi-dimension array initalizer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=305762c08975cd6e0bebd684ca910fa208792483;p=clang Implement multi-dimension array initalizer. Fix McCat/08-main test. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47286 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGExprAgg.cpp b/CodeGen/CGExprAgg.cpp index 0b12647efd..71f96aa675 100644 --- a/CodeGen/CGExprAgg.cpp +++ b/CodeGen/CGExprAgg.cpp @@ -82,6 +82,12 @@ public: void VisitConditionalOperator(const ConditionalOperator *CO); void VisitInitListExpr(InitListExpr *E); // case Expr::ChooseExprClass: + +private: + + llvm::Constant *GetConstantInit(InitListExpr *E, + const llvm::ArrayType *AType); + void EmitNonConstInit(Expr *E, llvm::Value *Dest, const llvm::Type *DestType); }; } // end anonymous namespace. @@ -230,81 +236,100 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) { CGF.EmitBlock(ContBlock); } -void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { - - unsigned NumInitElements = E->getNumInits(); - - if (!E->getType()->isArrayType()) { - CGF.WarnUnsupported(E, "aggregate init-list expression"); - return; - } - +llvm::Constant *AggExprEmitter::GetConstantInit(InitListExpr *E, + const llvm::ArrayType *AType) { std::vector ArrayElts; - const llvm::PointerType *APType = cast(DestPtr->getType()); - const llvm::ArrayType *AType = - cast(APType->getElementType()); + unsigned NumInitElements = E->getNumInits(); + const llvm::Type *ElementType = AType->getElementType(); + unsigned i; - // Copy initializer elements. - bool AllConstElements = true; - unsigned i = 0; for (i = 0; i != NumInitElements; ++i) { - if (llvm::Constant *C = + if (InitListExpr *InitList = dyn_cast(E->getInit(i))) { + assert(isa(ElementType) && "Invalid initilizer"); + llvm::Constant *C = + GetConstantInit(InitList, cast(ElementType)); + if (!C) return NULL; + ArrayElts.push_back(C); + } else if (llvm::Constant *C = dyn_cast(CGF.EmitScalarExpr(E->getInit(i)))) ArrayElts.push_back(C); - else { - AllConstElements = false; - break; - } + else + return NULL; } + // Remaining default initializers unsigned NumArrayElements = AType->getNumElements(); - const llvm::Type *ElementType = CGF.ConvertType(E->getInit(0)->getType()); - - if (AllConstElements) { - // Initialize remaining array elements. - for (/*Do not initialize i*/; i < NumArrayElements; ++i) + for (/*Do not initialize i*/; i < NumArrayElements; ++i) ArrayElts.push_back(llvm::Constant::getNullValue(ElementType)); - // Create global value to hold this array. - llvm::Constant *V = llvm::ConstantArray::get(AType, ArrayElts); - V = new llvm::GlobalVariable(V->getType(), true, - llvm::GlobalValue::InternalLinkage, - V, ".array", - &CGF.CGM.getModule()); - - EmitAggregateCopy(DestPtr, V , E->getType()); - return; - } + return llvm::ConstantArray::get(AType, ArrayElts); +} - // Emit indiviudal array element stores. - unsigned index = 0; - llvm::Value *NextVal = NULL; - llvm::Value *Idxs[] = { - llvm::Constant::getNullValue(llvm::Type::Int32Ty), - NULL - }; - - // Emit already seen constants initializers. - for (i = 0; i < ArrayElts.size(); i++) { - Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, index++); - NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2, ".array"); - Builder.CreateStore(ArrayElts[i], NextVal); - } +void AggExprEmitter::EmitNonConstInit(Expr *E, llvm::Value *DestPtr, + const llvm::Type *DestType) { + + if (const llvm::ArrayType *AType = dyn_cast(DestType)) { + unsigned NumInitElements = 0; + InitListExpr *InitList = NULL; + + if (E) { + InitList = cast(E); + NumInitElements = InitList->getNumInits(); + } + + llvm::Value *Idxs[] = { + llvm::Constant::getNullValue(llvm::Type::Int32Ty), + NULL + }; + llvm::Value *NextVal = NULL; + unsigned i; + for (i = 0; i != NumInitElements; ++i) { + Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2,".array"); + EmitNonConstInit(InitList->getInit(i), NextVal, AType->getElementType()); + } - // Emit remaining initializers - for (/*Do not initizalize i*/; i < NumInitElements; ++i) { - Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, index++); - NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2, ".array"); - llvm::Value *V = CGF.EmitScalarExpr(E->getInit(i)); - Builder.CreateStore(V, NextVal); + // Emit remaining default initializers + unsigned NumArrayElements = AType->getNumElements(); + for (/*Do not initialize i*/; i < NumArrayElements; ++i) { + Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2,".array"); + EmitNonConstInit(NULL, NextVal, AType->getElementType()); + } + + } else { + llvm::Value *V; + if (E) + V = CGF.EmitScalarExpr(E); + else + V = llvm::Constant::getNullValue(DestType); + Builder.CreateStore(V, DestPtr); } +} - // Emit remaining default initializers - for (/*Do not initialize i*/; i < NumArrayElements; ++i) { - Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, index++); - NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2, ".array"); - Builder.CreateStore(llvm::Constant::getNullValue(ElementType), NextVal); +void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { + + if (!E->getType()->isArrayType()) { + CGF.WarnUnsupported(E, "aggregate init-list expression"); + return; } + + const llvm::PointerType *APType = cast(DestPtr->getType()); + const llvm::ArrayType *AType = + cast(APType->getElementType()); + + llvm::Constant *V = GetConstantInit(E, AType); + if (V) { + // Create global value to hold this array. + V = new llvm::GlobalVariable(V->getType(), true, + llvm::GlobalValue::InternalLinkage, + V, ".array", + &CGF.CGM.getModule()); + + EmitAggregateCopy(DestPtr, V , E->getType()); + return; + } else + EmitNonConstInit(E, DestPtr, AType); } //===----------------------------------------------------------------------===// diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index 24f887422d..f773b8b8dd 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -1,7 +1,14 @@ // RUN: clang -emit-llvm %s -void f1() -{ - // Scalars in braces. - int a = { 1 }; - int b = { 1, 2 }; +void f1() { + // Scalars in braces. + int a = { 1 }; + int b = { 1, 2 }; +} + +void f2() { + int a[2][2] = { { 1, 2 }, { 3, 4 } }; + int b[3][3] = { { 1, 2 }, { 3, 4 } }; + int *c[2] = { &a[1][1], &b[2][2] }; + int *d[2][2] = { {&a[1][1], &b[2][2]}, {&a[0][0], &b[1][1]} }; + int *e[3][3] = { {&a[1][1], &b[2][2]}, {&a[0][0], &b[1][1]} }; }