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 /lib/CodeGen | |
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 32 |
1 files changed, 29 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. |