[cfe-commits] r77177 - /cfe/trunk/lib/CodeGen/CGExprConstant.cpp

Anders Carlsson andersca at mac.com
Sun Jul 26 18:23:52 PDT 2009


Author: andersca
Date: Sun Jul 26 20:23:51 2009
New Revision: 77177

URL: http://llvm.org/viewvc/llvm-project?rev=77177&view=rev
Log:
More work on bitfield support in the new constant struct builder.

Modified:
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=77177&r1=77176&r2=77177&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sun Jul 26 20:23:51 2009
@@ -119,6 +119,82 @@
     return true;
   }
   
+  bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, 
+                      const Expr *InitExpr) {
+    llvm::ConstantInt *CI = 
+      cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr, 
+                                                           Field->getType(), 
+                                                           CGF));
+    // FIXME: Can this ever happen?
+    if (!CI)
+      return false;
+    
+    if (FieldOffset > NextFieldOffsetInBytes * 8) {
+      // FIXME: Add padding.
+      return false;
+    }
+
+    uint64_t FieldSize = 
+      Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
+
+    llvm::APInt FieldValue = CI->getValue();
+    
+    // Promote the size of FieldValue if necessary
+    // FIXME: This should never occur, but currently it can because initializer
+    // constants are cast to bool, and because clang is not enforcing bitfield
+    // width limits.
+    if (FieldSize > FieldValue.getBitWidth())
+      FieldValue.zext(FieldSize);
+    
+    // Truncate the size of FieldValue to the bit field size.
+    if (FieldSize < FieldValue.getBitWidth())
+      FieldValue.trunc(FieldSize);
+
+    if (FieldOffset < NextFieldOffsetInBytes * 8) {
+      // FIXME: Part of the bitfield should go into the previous byte.
+      return false;
+    }
+    
+    while (FieldValue.getBitWidth() > 8) {
+      llvm::APInt Tmp;
+      
+      if (CGM.getTargetData().isBigEndian()) {
+        // We want the low bits.
+        Tmp = FieldValue.getLoBits(8);
+      } else {
+        // We want the high bits.
+        Tmp = FieldValue.getHiBits(8);
+      }
+      
+      Tmp.trunc(8);
+      Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
+      NextFieldOffsetInBytes++;
+      
+      FieldValue.trunc(FieldValue.getBitWidth() - 8);
+    }
+
+    assert(FieldValue.getBitWidth() > 0 &&
+           "Should have at least one bit left!");
+    assert(FieldValue.getBitWidth() <= 8 &&
+           "Should not have more than a byte left!");
+
+    if (FieldValue.getBitWidth() < 8) {
+      if (CGM.getTargetData().isBigEndian()) {
+        unsigned BitWidth = FieldValue.getBitWidth();
+      
+        FieldValue.zext(8);
+        FieldValue = FieldValue << (8 - BitWidth);
+      } else 
+        FieldValue.zext(8);
+    }
+
+    // Append the last element.
+    Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
+                                              FieldValue));
+    NextFieldOffsetInBytes++;
+    return true;
+  }
+  
   void AppendPadding(uint64_t NumBytes) {
     if (!NumBytes)
       return;
@@ -158,8 +234,9 @@
         if (!Field->getIdentifier())
           continue;
         
-        // FIXME: Bitfield support.
-        return false;
+        if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
+                            ILE->getInit(ElementNo)))
+          return false;
       } else {
         if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
                          ILE->getInit(ElementNo)))





More information about the cfe-commits mailing list