diff options
author | Devang Patel <dpatel@apple.com> | 2008-05-06 19:57:59 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2008-05-06 19:57:59 +0000 |
commit | d8ecd3c8f7716124e1efb278a46b6747c697668d (patch) | |
tree | 2c0e2ca9ebb29a110982cc2b5e28f46a616606fe | |
parent | fbfe82527dadb09c95609a742744d75a2322850c (diff) |
Fix PR2101 - Codegen crash during bitfield initialization.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50769 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 32 | ||||
-rw-r--r-- | test/CodeGen/bitfield-init.c | 4 |
2 files changed, 33 insertions, 3 deletions
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index a7f6670cb6..751cd3a077 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/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/test/CodeGen/bitfield-init.c b/test/CodeGen/bitfield-init.c new file mode 100644 index 0000000000..6e89e1185a --- /dev/null +++ b/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 }; + |