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 6f22adf..9c7991d 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -620,10 +620,13 @@
     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 @@
       // 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)