[cfe-commits] r83230 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp test/CodeGen/const-init.c
Anders Carlsson
andersca at mac.com
Thu Oct 1 19:15:21 PDT 2009
Author: andersca
Date: Thu Oct 1 21:15:20 2009
New Revision: 83230
URL: http://llvm.org/viewvc/llvm-project?rev=83230&view=rev
Log:
When building constant structs, check if the resulting LLVM struct will be bigger than the record layout size and use a packed struct if that's the case. Fixes PR5108.
Modified:
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/test/CodeGen/const-init.c
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=83230&r1=83229&r2=83230&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Oct 1 21:15:20 2009
@@ -37,10 +37,13 @@
unsigned NextFieldOffsetInBytes;
+ unsigned LLVMStructAlignment;
+
std::vector<llvm::Constant *> Elements;
ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
- : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0) { }
+ : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0),
+ LLVMStructAlignment(1) { }
bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
const Expr *InitExpr) {
@@ -61,44 +64,11 @@
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
- std::vector<llvm::Constant *> PackedElements;
-
assert(!Packed && "Alignment is wrong even with a packed struct!");
// Convert the struct to a packed struct.
- uint64_t ElementOffsetInBytes = 0;
-
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- llvm::Constant *C = Elements[i];
-
- unsigned ElementAlign =
- CGM.getTargetData().getABITypeAlignment(C->getType());
- uint64_t AlignedElementOffsetInBytes =
- llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
-
- if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
- // We need some padding.
- uint64_t NumBytes =
- AlignedElementOffsetInBytes - ElementOffsetInBytes;
-
- const llvm::Type *Ty = llvm::Type::getInt8Ty(CGF->getLLVMContext());
- if (NumBytes > 1)
- Ty = llvm::ArrayType::get(Ty, NumBytes);
-
- llvm::Constant *Padding = llvm::Constant::getNullValue(Ty);
- PackedElements.push_back(Padding);
- ElementOffsetInBytes += getSizeInBytes(Padding);
- }
-
- PackedElements.push_back(C);
- ElementOffsetInBytes += getSizeInBytes(C);
- }
-
- assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
- "Packing the struct changed its size!");
-
- Elements = PackedElements;
- Packed = true;
+ ConvertStructToPacked();
+
AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
}
@@ -115,7 +85,7 @@
// Add the field.
Elements.push_back(C);
NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
-
+ LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
return true;
}
@@ -270,6 +240,44 @@
AppendPadding(NumPadBytes);
}
+ void ConvertStructToPacked() {
+ std::vector<llvm::Constant *> PackedElements;
+ uint64_t ElementOffsetInBytes = 0;
+
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ llvm::Constant *C = Elements[i];
+
+ unsigned ElementAlign =
+ CGM.getTargetData().getABITypeAlignment(C->getType());
+ uint64_t AlignedElementOffsetInBytes =
+ llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
+
+ if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
+ // We need some padding.
+ uint64_t NumBytes =
+ AlignedElementOffsetInBytes - ElementOffsetInBytes;
+
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGF->getLLVMContext());
+ if (NumBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumBytes);
+
+ llvm::Constant *Padding = llvm::Constant::getNullValue(Ty);
+ PackedElements.push_back(Padding);
+ ElementOffsetInBytes += getSizeInBytes(Padding);
+ }
+
+ PackedElements.push_back(C);
+ ElementOffsetInBytes += getSizeInBytes(C);
+ }
+
+ assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
+ "Packing the struct changed its size!");
+
+ Elements = PackedElements;
+ LLVMStructAlignment = 1;
+ Packed = true;
+ }
+
bool Build(InitListExpr *ILE) {
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
@@ -306,11 +314,24 @@
// we must have a flexible array member at the end.
assert(RD->hasFlexibleArrayMember() &&
"Must have flexible array member if struct is bigger than type!");
-
+
// No tail padding is necessary.
return true;
}
+ uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes,
+ LLVMStructAlignment);
+
+ // Check if we need to convert the struct to a packed struct.
+ if (NextFieldOffsetInBytes <= LayoutSizeInBytes &&
+ LLVMSizeInBytes > LayoutSizeInBytes) {
+ assert(!Packed && "Size mismatch!");
+
+ ConvertStructToPacked();
+ assert(NextFieldOffsetInBytes == LayoutSizeInBytes &&
+ "Converting to packed did not help!");
+ }
+
// Append tail padding if necessary.
AppendTailPadding(Layout.getSize());
Modified: cfe/trunk/test/CodeGen/const-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/const-init.c?rev=83230&r1=83229&r2=83230&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/const-init.c (original)
+++ cfe/trunk/test/CodeGen/const-init.c Thu Oct 1 21:15:20 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -verify -emit-llvm -o %t %s &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -verify -emit-llvm -o %t %s | FileCheck %s --input-file=%t &&
#include <stdint.h>
@@ -47,6 +47,12 @@
// RUN: grep '@g10 = global i32 0' %t &&
int g10 = (2.0 + 3.0i) * (5.0 + 7.0i) != (-11.0 + 29.0i);
+// PR5108
+// CHECK: @ss = global %4 <{ i32 0, i8 7 }>, align 1
+struct s {
+ unsigned long a;
+ unsigned long b:3;
+} __attribute__((__packed__)) ss = { .a = 0x0, .b = 7, };
// Global references
// RUN: grep '@g11.l0 = internal global i32 ptrtoint (i32 ()\* @g11 to i32)' %t &&
More information about the cfe-commits
mailing list