On Jan 24, 2008 8:09 PM, Sanghyeon Seo <[EMAIL PROTECTED]> wrote:
> This test program crashes in CodeGen.
> struct s { short a; int b; } x = {1, 1};
>
> "struct s" converts to LLVM type {i16, i8, i8, i32}, padded with i8.
> CodeGen attempts llvm::ConstantStruct::get({i16, i8, i8, i32}, {1, 1})
> and crashes, since the type has 4 elements but initializer has only 2.
Here's a fix. It doesn't completely implement struct initializer
codegen, but it's enough to codegen all fully braced initializers that
don't initialize bitfields.
-Eli
Index: CodeGen/CodeGenModule.cpp
===================================================================
--- CodeGen/CodeGenModule.cpp (revision 46353)
+++ CodeGen/CodeGenModule.cpp (working copy)
@@ -293,13 +293,6 @@
/// struct typed variables.
static llvm::Constant *GenerateAggregateInit(const InitListExpr *ILE,
CodeGenModule &CGM) {
- if (ILE->getType()->isVoidType()) {
- // FIXME: Remove this when sema of initializers is finished (and the code
- // below).
- CGM.WarnUnsupported(ILE, "initializer");
- return 0;
- }
-
assert((ILE->getType()->isArrayType() || ILE->getType()->isStructureType() ||
ILE->getType()->isVectorType()) &&
"Bad type for init list!");
@@ -311,38 +304,76 @@
const llvm::CompositeType *CType =
cast<llvm::CompositeType>(Types.ConvertType(ILE->getType()));
assert(CType);
- std::vector<llvm::Constant*> Elts;
-
+
+ if (ILE->getType()->isStructureType()) {
+ const llvm::StructType *SType = cast<llvm::StructType>(CType);
+ const RecordDecl* structDecl =
ILE->getType()->getAsRecordType()->getDecl();
+ // The number of declarations in the C struct
+ unsigned numMembers = structDecl->getNumMembers() -
+ structDecl->hasFlexibleArrayMember();
+ // The number of members in the raw LLVM struct.
+ unsigned numLLVMElements = SType->getNumElements();
+ // At the end of the following two loops, Elts will contain
+ // initializers for all the members of the LLVM struct.
+ std::vector<llvm::Constant*> Elts(numLLVMElements);
+ for (unsigned curMember = 0, curInit = 0; curMember < numMembers;
++curMember) {
+ if (curInit >= ILE->getNumInits()) {
+ // No more initializers; the rest of the struct is filled
+ // with null below.
+ break;
+ }
+ const FieldDecl *curField = structDecl->getMember(curMember);
+ if (!curField->getIdentifier()) {
+ // Initializers can't initialize unnamed fields, e.g. "int : 20;"
+ continue;
+ }
+ const Expr* expr = ILE->getInit(curInit);
+ ++curInit;
+ // FIXME: This doesn't work properly for initializers
+ // that aren't fully braced.
+ llvm::Constant* fieldValue = GenerateConstantExpr(expr, CGM);
+ assert(!curField->isBitField() && "Cannot initialize bitfields yet");
+ // Fill in the appropriate field in the LLVM struct.
+ // Types.getLLVMFieldNo(curField) is often equal to curMember,
+ // but padding and bitfields mess that up, so it's simpler
+ // to just grab the right field.
+ Elts[Types.getLLVMFieldNo(curField)] = fieldValue;
+ }
+ for (unsigned i = 0; i < Elts.size(); i++) {
+ if (Elts[i] == 0) {
+ // Fill in all the uninitialized members with null
+ // In theory, we could fill in padding fields with undef,
+ // but it would be more complicated.
+ Elts[i] = llvm::Constant::getNullValue(SType->getElementType(i));
+ }
+ }
+ return llvm::ConstantStruct::get(SType, Elts);
+ }
+
+ std::vector<llvm::Constant*> Elts;
// Initialising an array requires us to automatically initialise any
// elements that have not been initialised explicitly
const llvm::ArrayType *AType = 0;
const llvm::Type *AElemTy = 0;
unsigned NumArrayElements = 0;
-
+
// If this is an array, we may have to truncate the initializer
if ((AType = dyn_cast<llvm::ArrayType>(CType))) {
NumArrayElements = AType->getNumElements();
AElemTy = AType->getElementType();
NumInitableElts = std::min(NumInitableElts, NumArrayElements);
}
-
+
// Copy initializer elements.
unsigned i = 0;
for (i = 0; i < NumInitableElts; ++i) {
llvm::Constant *C = GenerateConstantExpr(ILE->getInit(i), CGM);
- // FIXME: Remove this when sema of initializers is finished (and the code
- // above).
- if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) {
- if (ILE->getType()->isVoidType()) return 0;
- return llvm::UndefValue::get(CType);
- }
assert (C && "Failed to create initialiser expression");
Elts.push_back(C);
}
- if (ILE->getType()->isStructureType())
- return llvm::ConstantStruct::get(cast<llvm::StructType>(CType), Elts);
-
+ // FIXME: What about a vector initializer that doesn't have
+ // enough elements?
if (ILE->getType()->isVectorType())
return llvm::ConstantVector::get(cast<llvm::VectorType>(CType), Elts);
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev