From 34994cbcbf83dee141ee63c8fdf513932b6952b0 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 30 May 2008 19:58:50 +0000 Subject: Fix and enable generating general union initializers. Essentially, what this does is reconstruct the type for structs and arrays if the type wouldn't be compatible otherwise. The assertion about packing in the struct type reconstruction code sucks, but I don't see any obvious way to fix it. Maybe we need a general utility method to take a list of types and alignments and try to construct an unpacked type if possible? llvm-svn: 51785 --- clang/lib/CodeGen/CGExprConstant.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'clang/lib/CodeGen') diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 1144cf1c915..4cb3c7bb2a0 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -92,15 +92,26 @@ public: // Copy initializer elements. unsigned i = 0; + bool RewriteType = false; for (; i < NumInitableElts; ++i) { llvm::Constant *C = Visit(ILE->getInit(i)); + RewriteType |= (C->getType() != ElemTy); Elts.push_back(C); } - + // Initialize remaining array elements. for (; i < NumElements; ++i) Elts.push_back(llvm::Constant::getNullValue(ElemTy)); + if (RewriteType) { + // FIXME: Try to avoid packing the array + std::vector Types; + for (unsigned i = 0; i < Elts.size(); ++i) + Types.push_back(Elts[i]->getType()); + const llvm::StructType *SType = llvm::StructType::get(Types, true); + return llvm::ConstantStruct::get(SType, Elts); + } + return llvm::ConstantArray::get(AType, Elts); } @@ -166,6 +177,7 @@ public: // Copy initializer elements. Skip padding fields. unsigned EltNo = 0; // Element no in ILE int FieldNo = 0; // Field no in RecordDecl + bool RewriteType = false; while (EltNo < ILE->getNumInits() && FieldNo < RD->getNumMembers()) { FieldDecl* curField = RD->getMember(FieldNo); FieldNo++; @@ -175,22 +187,27 @@ public: if (curField->isBitField()) { InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo)); } else { - Elts[CGM.getTypes().getLLVMFieldNo(curField)] = - Visit(ILE->getInit(EltNo)); + unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(curField); + llvm::Constant* C = Visit(ILE->getInit(EltNo)); + RewriteType |= (C->getType() != Elts[FieldNo]->getType()); + Elts[FieldNo] = C; } EltNo++; } + if (RewriteType) { + // FIXME: Make this work for non-packed structs + assert(SType->isPacked() && "Cannot recreate unpacked structs"); + std::vector Types; + for (unsigned i = 0; i < Elts.size(); ++i) + Types.push_back(Elts[i]->getType()); + SType = llvm::StructType::get(Types, true); + } + return llvm::ConstantStruct::get(SType, Elts); } llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) { - // FIXME: Need to make this work correctly for unions in structs/arrays - CGM.WarnUnsupported(ILE, "bitfield initialization"); - return llvm::UndefValue::get(CGM.getTypes().ConvertType(ILE->getType())); - - // Following is a partial implementation; it doesn't work correctly - // because the parent struct/arrays don't adapt their type yet, though RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); const llvm::Type *Ty = ConvertType(ILE->getType()); -- cgit v1.2.3