aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-05-30 19:58:50 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-05-30 19:58:50 +0000
commita04a1538ee5e286e94e3374caf51ba1094d289b0 (patch)
treeb3911cdcf2b2f0562155c2728df1d4ddb7db578e /lib/CodeGen/CGExprConstant.cpp
parent77ba708819285931932ecd33691a672bb59d221a (diff)
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? git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp35
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 1144cf1c91..4cb3c7bb2a 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/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<const llvm::Type*> 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<const llvm::Type*> 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());