]> granicus.if.org Git - clang/commitdiff
x86_64 ABI: Implement classification for bit-fields.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 17 Feb 2009 02:45:44 +0000 (02:45 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 17 Feb 2009 02:45:44 +0000 (02:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64727 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp

index 6f22adfc8ca2ce058e110e3eef37c23c66b8f67e..9c7991d1cd374d642f575a103fd0dda3564f2d4a 100644 (file)
@@ -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)