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
This commit is contained in:
Eli Friedman 2008-05-30 19:58:50 +00:00
parent b6725054b8
commit 34994cbcbf
2 changed files with 57 additions and 9 deletions

View File

@ -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());

View File

@ -0,0 +1,31 @@
// RUN: clang -emit-llvm < %s -o -
// A nice and complicated initialization example with unions from Python
typedef int Py_ssize_t;
typedef union _gc_head {
struct {
union _gc_head *gc_next;
union _gc_head *gc_prev;
Py_ssize_t gc_refs;
} gc;
long double dummy; /* force worst-case alignment */
} PyGC_Head;
struct gc_generation {
PyGC_Head head;
int threshold; /* collection threshold */
int count; /* count of allocations or collections of younger
generations */
};
#define NUM_GENERATIONS 3
#define GEN_HEAD(n) (&generations[n].head)
/* linked lists of container objects */
struct gc_generation generations[NUM_GENERATIONS] = {
/* PyGC_Head, threshold, count */
{{{GEN_HEAD(0), GEN_HEAD(0), 0}}, 700, 0},
{{{GEN_HEAD(1), GEN_HEAD(1), 0}}, 10, 0},
{{{GEN_HEAD(2), GEN_HEAD(2), 0}}, 10, 0},
};