Always use packed structs. This isn't really very nice, but there's
nothing fundamentally wrong with it. Emitting unpacked structs where
possible is more work for almost no practical benefit. We'll probably
want to fix it at some point anyway, but it's low priority.
The issue with long double in particular is that LLVM thinks an X86 long
double is 10 bytes, while clang considers it for all purposes to be
either 12 or 16 bytes, depending on the platform, even in a packed
struct.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51673 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 5efde77..ec4f6df 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -482,14 +482,13 @@
// FIXME : Use SmallVector
uint64_t llvmSize = 0;
std::vector<const llvm::Type*> LLVMFields;
- bool packedStruct = false;
int NumMembers = RD.getNumMembers();
for (int curField = 0; curField < NumMembers; curField++) {
const FieldDecl *FD = RD.getMember(curField);
uint64_t offset = RL.getFieldOffset(curField);
const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType());
- uint64_t size = CGT.getTargetData().getABITypeSize(Ty) * 8;
+ uint64_t size = CGT.getTargetData().getTypeStoreSizeInBits(Ty);
if (FD->isBitField()) {
Expr *BitWidth = FD->getBitWidth();
@@ -513,12 +512,6 @@
llvmSize += 8;
}
- unsigned Align = CGT.getTargetData().getABITypeAlignment(Ty) * 8;
- if (llvmSize % Align)
- packedStruct = true;
- else if (offset == 0 && RL.getAlignment() % Align)
- packedStruct = true;
-
llvmSize += size;
CGT.addFieldInfo(FD, LLVMFields.size());
LLVMFields.push_back(Ty);
@@ -530,7 +523,7 @@
llvmSize += 8;
}
- STy = llvm::StructType::get(LLVMFields, packedStruct);
+ STy = llvm::StructType::get(LLVMFields, true);
assert(CGT.getTargetData().getABITypeSizeInBits(STy) == RL.getSize());
}
diff --git a/test/CodeGen/struct-x86-darwin.c b/test/CodeGen/struct-x86-darwin.c
index 3d3729d..68e6d72 100644
--- a/test/CodeGen/struct-x86-darwin.c
+++ b/test/CodeGen/struct-x86-darwin.c
@@ -1,16 +1,14 @@
-// RUN: clang < %s -emit-llvm > %t1
-// Run grep "STest1 = type { i32, \[4 x i16\], double }" %t1 &&
-// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1 &&
-// RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1 &&
-// RUN: grep "STestB1 = type { i8, i8 }" %t1 &&
-// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1 &&
-// RUN: grep "STestB3 = type { i8, i8 }" %t1 &&
-// RUN: grep "STestB4 = type { i8, i8, i8, i8 }" %t1
-// RUN: grep "STestB5 = type { i8, i8, i8, i8, i8, i8 }" %t1
-// RUN: grep "STestB6 = type { i8, i8, i8, i8 }" %t1
+// RUN: clang < %s -emit-llvm > %t1 -triple=i686-apple-darwin9
+// Run grep "STest1 = type <{ i32, \[4 x i16\], double }>" %t1 &&
+// RUN: grep "STest2 = type <{ i16, i16, i32, i32 }>" %t1 &&
+// RUN: grep "STest3 = type <{ i8, i8, i16, i32 }>" %t1 &&
+// RUN: grep "STestB1 = type <{ i8, i8 }>" %t1 &&
+// RUN: grep "STestB2 = type <{ i8, i8, i8 }>" %t1 &&
+// RUN: grep "STestB3 = type <{ i8, i8 }>" %t1 &&
+// RUN: grep "STestB4 = type <{ i8, i8, i8, i8 }>" %t1
+// RUN: grep "STestB5 = type <{ i8, i8, i8, i8, i8, i8 }>" %t1
+// RUN: grep "STestB6 = type <{ i8, i8, i8, i8 }>" %t1
// Test struct layout for x86-darwin target
-// FIXME : Enable this test for x86-darwin only. At the moment clang hard codes
-// x86-darwin as the target
struct STest1 {int x; short y[4]; double z; } st1;
struct STest2 {short a,b; int c,d; } st2;
diff --git a/test/CodeGen/struct.c b/test/CodeGen/struct.c
index f17a7af..f567a0b 100644
--- a/test/CodeGen/struct.c
+++ b/test/CodeGen/struct.c
@@ -163,3 +163,6 @@
/* Attribute packed */
struct __attribute__((packed)) S2839 { double a[19]; signed char b; } s2839[5];
+
+struct __attribute__((packed)) SS { long double a; char b; } SS;
+