summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevang Patel <dpatel@apple.com>2008-05-06 19:57:59 +0000
committerDevang Patel <dpatel@apple.com>2008-05-06 19:57:59 +0000
commit243d5cd2833cd124ffda807189f17eb8ca3442e7 (patch)
tree4f8b6098ce26d8bc8c91185194a6a931dd01e965
parent6ea927b1d7624bed517daf3bcd7a018dbf91927a (diff)
downloadbcm5719-llvm-243d5cd2833cd124ffda807189f17eb8ca3442e7.tar.gz
bcm5719-llvm-243d5cd2833cd124ffda807189f17eb8ca3442e7.zip
Fix PR2101 - Codegen crash during bitfield initialization.
llvm-svn: 50769
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp32
-rw-r--r--clang/test/CodeGen/bitfield-init.c4
2 files changed, 33 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index a7f6670cb6e..751cd3a0777 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -521,7 +521,28 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
unsigned StructAlign = RL.getAlignment();
if (llvmSize % StructAlign) {
unsigned StructPadding = StructAlign - (llvmSize % StructAlign);
- addPaddingFields(llvmSize + StructPadding);
+ bool needStructPadding = true;
+ if (!LLVMFields.empty()) {
+ const llvm::Type *LastFieldType = LLVMFields.back();
+ const llvm::Type *LastFieldDeclType =
+ CGT.ConvertTypeRecursive(FieldDecls.back()->getType());
+ if (LastFieldType != LastFieldDeclType) {
+ unsigned LastFieldTypeSize =
+ CGT.getTargetData().getABITypeSizeInBits(LastFieldType);
+ unsigned LastFieldDeclTypeSize =
+ CGT.getTargetData().getABITypeSizeInBits(LastFieldDeclType);
+ if (LastFieldDeclTypeSize > LastFieldTypeSize
+ && StructPadding == (LastFieldDeclTypeSize - LastFieldTypeSize)) {
+ // Replace last LLVMField with a LastFieldDeclType field will
+ // to avoid extra padding fields.
+ LLVMFields.pop_back();
+ LLVMFields.push_back(LastFieldDeclType);
+ needStructPadding = false;
+ }
+ }
+ }
+ if (needStructPadding)
+ addPaddingFields(llvmSize + StructPadding);
}
STy = llvm::StructType::get(LLVMFields);
@@ -533,8 +554,13 @@ void RecordOrganizer::addPaddingFields(unsigned WaterMark) {
assert(WaterMark >= llvmSize && "Invalid padding Field");
unsigned RequiredBits = WaterMark - llvmSize;
unsigned RequiredBytes = (RequiredBits + 7) / 8;
- for (unsigned i = 0; i != RequiredBytes; ++i)
- addLLVMField(llvm::Type::Int8Ty, true);
+ if (RequiredBytes == 1)
+ // This is a bitfield that is using few bits from this byte.
+ // It is not a padding field.
+ addLLVMField(llvm::Type::Int8Ty, false);
+ else
+ for (unsigned i = 0; i != RequiredBytes; ++i)
+ addLLVMField(llvm::Type::Int8Ty, true);
}
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
diff --git a/clang/test/CodeGen/bitfield-init.c b/clang/test/CodeGen/bitfield-init.c
new file mode 100644
index 00000000000..6e89e1185a4
--- /dev/null
+++ b/clang/test/CodeGen/bitfield-init.c
@@ -0,0 +1,4 @@
+// RUN: clang %s -emit-llvm
+typedef struct { unsigned int i: 1; } c;
+const c d = { 1 };
+
OpenPOWER on IntegriCloud