aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-04-13 18:16:19 +0000
committerChris Lattner <sabre@nondot.org>2010-04-13 18:16:19 +0000
commit8ce9e451b421e4c941bc120bcc7f422457656d63 (patch)
tree692a75c4f5028de093f23354cf3799bff90b6fe4 /lib/CodeGen/CGExprConstant.cpp
parentb5e8156ebd6accd27daeaae6971597c45d5e5139 (diff)
Rework the ConstStructBuilder code to emit missing initializer
elements with explicit zero values instead of with tail padding. On an example like this: struct foo { int a; int b; }; struct foo fooarray[] = { {1, 2}, {4}, }; We now lay this out as: @fooarray = global [2 x %struct.foo] [%struct.foo { i32 1, i32 2 }, %struct.foo { i32 4, i32 0 }] instead of as: @fooarray = global %0 <{ %struct.foo { i32 1, i32 2 }, %1 { i32 4, [4 x i8] zeroinitializer } }> Preserving both the struct type of the second element, but also the array type of the entire thing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101155 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp56
1 files changed, 31 insertions, 25 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 8d16ed7ad7..7da7554e2c 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -50,10 +50,10 @@ private:
LLVMStructAlignment(1) { }
bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
- const Expr *InitExpr);
+ llvm::Constant *InitExpr);
bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
- const Expr *InitExpr);
+ llvm::Constant *InitExpr);
void AppendPadding(uint64_t NumBytes);
@@ -74,18 +74,18 @@ private:
};
bool ConstStructBuilder::
-AppendField(const FieldDecl *Field, uint64_t FieldOffset, const Expr *InitExpr){
+AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitCst) {
uint64_t FieldOffsetInBytes = FieldOffset / 8;
assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
&& "Field offset mismatch!");
// Emit the field.
- llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
- if (!C)
+ if (!InitCst)
return false;
- unsigned FieldAlignment = getAlignment(C);
+ unsigned FieldAlignment = getAlignment(InitCst);
// Round up the field offset to the alignment of the field type.
uint64_t AlignedNextFieldOffsetInBytes =
@@ -111,8 +111,9 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset, const Expr *InitExpr){
}
// Add the field.
- Elements.push_back(C);
- NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
+ Elements.push_back(InitCst);
+ NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes +
+ getSizeInBytes(InitCst);
if (Packed)
assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
@@ -124,11 +125,8 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset, const Expr *InitExpr){
bool ConstStructBuilder::
AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
- const Expr *InitExpr) {
- llvm::ConstantInt *CI =
- cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr,
- Field->getType(),
- CGF));
+ llvm::Constant *InitCst) {
+ llvm::ConstantInt *CI = cast_or_null<llvm::ConstantInt>(InitCst);
// FIXME: Can this ever happen?
if (!CI)
return false;
@@ -323,26 +321,34 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
unsigned FieldNo = 0;
unsigned ElementNo = 0;
for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- ElementNo < ILE->getNumInits() && Field != FieldEnd;
- ++Field, ++FieldNo) {
+ FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+
+ // If this is a union, skip all the fields that aren't being initialized.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
continue;
- if (Field->isBitField()) {
- if (!Field->getIdentifier())
- continue;
+ // Don't emit anonymous bitfields, they just affect layout.
+ if (Field->isBitField() && !Field->getIdentifier())
+ continue;
- if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
- ILE->getInit(ElementNo)))
+ // Get the initializer. A struct can include fields without initializers,
+ // we just use explicit null values for them.
+ llvm::Constant *EltInit;
+ if (ElementNo < ILE->getNumInits())
+ EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++),
+ Field->getType(), CGF);
+ else
+ EltInit = CGM.EmitNullConstant(Field->getType());
+
+ if (!Field->isBitField()) {
+ // Handle non-bitfield members.
+ if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
return false;
} else {
- if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
- ILE->getInit(ElementNo)))
+ // Otherwise we have a bitfield.
+ if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
return false;
}
-
- ElementNo++;
}
uint64_t LayoutSizeInBytes = Layout.getSize() / 8;