From: Daniel Dunbar Date: Tue, 17 Feb 2009 02:45:44 +0000 (+0000) Subject: x86_64 ABI: Implement classification for bit-fields. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dd81d44fac2631e6ca9fe1f52366aea0f51b03e1;p=clang x86_64 ABI: Implement classification for bit-fields. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64727 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 6f22adfc8c..9c7991d1cd 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -620,10 +620,13 @@ void X86_64ABIInfo::classify(QualType Ty, for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i, ++idx) { uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); + bool BitField = i->isBitField(); // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned // fields, it has class MEMORY. - if (Offset % Context.getTypeAlign(i->getType())) { + // + // Note, skip this test for bitfields, see below. + if (!BitField && Offset % Context.getTypeAlign(i->getType())) { Lo = Memory; return; } @@ -635,7 +638,28 @@ void X86_64ABIInfo::classify(QualType Ty, // separately. Each eightbyte gets initialized to class // NO_CLASS. Class FieldLo, FieldHi; - classify(i->getType(), Context, Offset, FieldLo, FieldHi); + + // Bitfields require special handling, they do not force the + // structure to be passed in memory even if unaligned, and + // therefore they can straddle an eightbyte. + if (BitField) { + uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); + uint64_t Size = + i->getBitWidth()->getIntegerConstantExprValue(Context).getZExtValue(); + + uint64_t EB_Lo = Offset / 64; + uint64_t EB_Hi = (Offset + Size - 1) / 64; + FieldLo = FieldHi = NoClass; + if (EB_Lo) { + assert(EB_Hi == EB_Lo && "Invalid classification, type > 16 bytes."); + FieldLo = NoClass; + FieldHi = Integer; + } else { + FieldLo = Integer; + FieldHi = EB_Hi ? Integer : NoClass; + } + } else + classify(i->getType(), Context, Offset, FieldLo, FieldHi); Lo = merge(Lo, FieldLo); Hi = merge(Hi, FieldHi); if (Lo == Memory || Hi == Memory)