зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
b5e8156ebd
Коммит
8ce9e451b4
|
@ -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;
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
// CHECK: @test5w = global %0 { i32 2, [4 x i8] zeroinitializer }
|
||||
// CHECK: @test5y = global %union.test5u { double 7.300000e+0{{[0]*}}1 }
|
||||
|
||||
// CHECK: @test6.x = internal constant %1 { i8 1, i8 2, i32 3, [4 x i8] zeroinitializer }
|
||||
// CHECK: @test6.x = internal constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
|
||||
|
||||
// CHECK: @test7 = global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]
|
||||
|
||||
void test1() {
|
||||
// This should codegen as a "@test1.x" global.
|
||||
const int x[] = { 1, 2, 3, 4, 6, 8, 9, 10, 123, 231, 123,23 };
|
||||
|
@ -74,3 +77,10 @@ void test6() {
|
|||
struct SelectDest x = {1, 2, 3};
|
||||
test6f(&x);
|
||||
}
|
||||
|
||||
// rdar://7657600
|
||||
struct test7s { int a; int b; } test7[] = {
|
||||
{1, 2},
|
||||
{4},
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче