Implement union layout support.

llvm-svn: 76846
This commit is contained in:
Anders Carlsson 2009-07-23 03:43:54 +00:00
parent 307846fe67
commit 697f65943d
2 changed files with 48 additions and 5 deletions

View File

@ -27,6 +27,11 @@ using namespace clang;
using namespace CodeGen;
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (D->isUnion()) {
LayoutUnion(D);
return;
}
if (const PackedAttr* PA = D->getAttr<PackedAttr>())
StructPacking = PA->getAlignment();
@ -141,11 +146,49 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
return true;
}
void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!");
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
const llvm::Type *Ty = 0;
uint64_t Size = 0;
unsigned Align = 0;
unsigned FieldNo = 0;
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
assert(Layout.getFieldOffset(FieldNo) == 0 &&
"Union field offset did not start at the beginning of record!");
const llvm::Type *FieldTy =
Types.ConvertTypeForMemRecursive(Field->getType());
unsigned FieldAlign = Types.getTargetData().getTypeAllocSize(FieldTy);
uint64_t FieldSize = Types.getTargetData().getABITypeAlignment(FieldTy);
if (FieldAlign < Align)
continue;
if (FieldAlign > Align || FieldSize > Size) {
Ty = FieldTy;
Align = FieldAlign;
Size = FieldSize;
}
}
// Now add our field.
if (Ty)
AppendField(0, Size, Ty);
// Append tail padding.
if (Layout.getSize() / 8 > Size)
AppendPadding(Layout.getSize() / 8, Align);
}
bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
assert(!D->isUnion() && "Can't call LayoutFields on a union!");
const ASTRecordLayout &Layout =
Types.getContext().getASTRecordLayout(D);
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
unsigned FieldNo = 0;
for (RecordDecl::field_iterator Field = D->field_begin(),
@ -241,9 +284,6 @@ CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types,
const RecordDecl *D) {
CGRecordLayoutBuilder Builder(Types);
if (D->isUnion())
return 0;
Builder.Layout(D);
// FIXME: Once this works well enough, enable it.

View File

@ -83,6 +83,9 @@ class CGRecordLayoutBuilder {
/// Layout - Will layout a RecordDecl.
void Layout(const RecordDecl *D);
/// LayoutUnion - Will layout a union RecordDecl.
void LayoutUnion(const RecordDecl *D);
/// LayoutField - try to layout all fields in the record decl.
/// Returns false if the operation failed because the struct is not packed.
bool LayoutFields(const RecordDecl *D);