More work on the constant struct builder. We can now convert the struct to a packed struct when necessary.

llvm-svn: 77038
This commit is contained in:
Anders Carlsson 2009-07-25 01:40:29 +00:00
parent c1a5cfa9a0
commit 3b484b928d
1 changed files with 40 additions and 3 deletions

View File

@ -61,13 +61,50 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
// FIXME: Must convert the struct to a packed struct.
return false;
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::Int8Ty;
if (NumBytes > 1)
Ty = CGM.getLLVMContext().getArrayType(Ty, NumBytes);
llvm::Constant *Padding = CGM.getLLVMContext().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;
AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
}
if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
// We need to append padding.
AppendPadding(FieldOffsetInBytes - AlignedNextFieldOffsetInBytes);
AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);
assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
"Did not add enough padding!");