[cfe-commits] r101178 - in /cfe/trunk/lib/CodeGen: CGObjCMac.cpp CGRecordLayout.h CGRecordLayoutBuilder.cpp

Daniel Dunbar daniel at zuster.org
Tue Apr 13 13:58:56 PDT 2010


Author: ddunbar
Date: Tue Apr 13 15:58:55 2010
New Revision: 101178

URL: http://llvm.org/viewvc/llvm-project?rev=101178&view=rev
Log:
IRgen: Enhance CGBitFieldInfo with enough information to fully describe the "policy" with which a bit-field should be accessed.
 - For now, these policies are computed to match the current IRgen strategy, although the new information isn't being used yet (except in -fdump-record-layouts).

 - Design comments appreciated.

Modified:
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayout.h
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Apr 13 15:58:55 2010
@@ -129,6 +129,17 @@
     new (CGF.CGM.getContext()) CGBitFieldInfo(
       LTy, FieldNo, BitOffset, BitFieldSize, IvarTy->isSignedIntegerType());
 
+  // We always construct a single, possibly unaligned, access for this case.
+  Info->setNumComponents(1);
+  CGBitFieldInfo::AccessInfo &AI = Info->getComponent(0);
+  AI.FieldIndex = 0;
+  AI.FieldByteOffset = 0;
+  AI.FieldBitStart = BitOffset;
+  AI.AccessWidth = CGF.CGM.getContext().getTypeSize(IvarTy);
+  AI.AccessAlignment = 0;
+  AI.TargetBitOffset = 0;
+  AI.TargetBitWidth = BitFieldSize;
+
   // FIXME: We need to set a very conservative alignment on this, or make sure
   // that the runtime is doing the right thing.
   return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());

Modified: cfe/trunk/lib/CodeGen/CGRecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayout.h?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayout.h (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayout.h Tue Apr 13 15:58:55 2010
@@ -20,10 +20,74 @@
 namespace clang {
 namespace CodeGen {
 
-/// Helper object for describing how to generate the code for access to a
+/// \brief Helper object for describing how to generate the code for access to a
 /// bit-field.
+///
+/// This structure is intended to describe the "policy" of how the bit-field
+/// should be accessed, which may be target, language, or ABI dependent.
 class CGBitFieldInfo {
 public:
+  /// Descriptor for a single component of a bit-field access. The entire
+  /// bit-field is constituted of a bitwise OR of all of the individual
+  /// components.
+  ///
+  /// Each component describes an accessed value, which is how the component
+  /// should be transferred to/from memory, and a target placement, which is how
+  /// that component fits into the constituted bit-field. The pseudo-IR for a
+  /// load is:
+  ///
+  ///   %0 = gep %base, 0, FieldIndex
+  ///   %1 = gep (i8*) %0, FieldByteOffset
+  ///   %2 = (i(AccessWidth) *) %1
+  ///   %3 = load %2, align AccessAlignment
+  ///   %4 = shr %3, FieldBitStart
+  ///
+  /// and the composed bit-field is formed as the boolean OR of all accesses,
+  /// masked to TargetBitWidth bits and shifted to TargetBitOffset.
+  struct AccessInfo {
+    /// Offset of the field to load in the LLVM structure, if any.
+    unsigned FieldIndex;
+
+    /// Byte offset from the field address, if any. This should generally be
+    /// unused as the cleanest IR comes from having a well-constructed LLVM type
+    /// with proper GEP instructions, but sometimes its use is required, for
+    /// example if an access is intended to straddle an LLVM field boundary.
+    unsigned FieldByteOffset;
+
+    /// Bit offset in the accessed value to use. The width is implied by \see
+    /// TargetBitWidth.
+    unsigned FieldBitStart;
+
+    /// Bit width of the memory access to perform.
+    unsigned AccessWidth;
+
+    /// The alignment of the memory access, or 0 if the default alignment should
+    /// be used.
+    //
+    // FIXME: Remove use of 0 to encode default, instead have IRgen do the right
+    // thing when it generates the code, if avoiding align directives is
+    // desired.
+    unsigned AccessAlignment;
+
+    /// Offset for the target value.
+    unsigned TargetBitOffset;
+
+    /// Number of bits in the access that are destined for the bit-field.
+    unsigned TargetBitWidth;
+  };
+
+private:
+  /// The number of access components to use.
+  unsigned NumComponents;
+
+  /// The components to use to access the bit-field. We may need up to three
+  /// separate components to support up to i64 bit-field access (4 + 2 + 1 byte
+  /// accesses).
+  //
+  // FIXME: De-hardcode this, just allocate following the struct.
+  AccessInfo Components[3];
+
+public:
   CGBitFieldInfo(const llvm::Type *FieldTy, unsigned FieldNo,
                  unsigned Start, unsigned Size, bool IsSigned)
     : FieldTy(FieldTy), FieldNo(FieldNo),
@@ -36,6 +100,24 @@
   unsigned Size;
   bool IsSigned : 1;
 
+public:
+  bool isSigned() const { return IsSigned; }
+
+  unsigned getNumComponents() const { return NumComponents; }
+  void setNumComponents(unsigned Value) {
+    assert(Value < 4 && "Invalid number of components!");
+    NumComponents = Value;
+  }
+
+  const AccessInfo &getComponent(unsigned Index) const {
+    assert(Index < getNumComponents() && "Invalid access!");
+    return Components[Index];
+  }
+  AccessInfo &getComponent(unsigned Index) {
+    assert(Index < getNumComponents() && "Invalid access!");
+    return Components[Index];
+  }
+
   void print(llvm::raw_ostream &OS) const;
   void dump() const;
 };

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Tue Apr 13 15:58:55 2010
@@ -150,12 +150,45 @@
                                           uint64_t FieldOffset,
                                           uint64_t FieldSize) {
   const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
-  uint64_t TypeSizeInBits = Types.getTargetData().getTypeAllocSize(Ty) * 8;
+  uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
+  uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
 
   bool IsSigned = FD->getType()->isSignedIntegerType();
   CGBitFieldInfo BFI(Ty, FieldOffset / TypeSizeInBits,
                      FieldOffset % TypeSizeInBits, FieldSize, IsSigned);
 
+  // The current policy is to always access the bit-field using the source type
+  // of the bit-field. With the C bit-field rules, this implies that we always
+  // use either one or two accesses, and two accesses can only occur with a
+  // packed structure when the bit-field straddles an alignment boundary.
+  unsigned LowBits = std::min(FieldSize, TypeSizeInBits - BFI.Start);
+  bool NeedsHighAccess = LowBits != FieldSize;
+  BFI.setNumComponents(1 + NeedsHighAccess);
+
+  // FIXME: This access policy is probably wrong on big-endian systems.
+  CGBitFieldInfo::AccessInfo &LowAccess = BFI.getComponent(0);
+  LowAccess.FieldIndex = 0;
+  LowAccess.FieldByteOffset =
+    TypeSizeInBytes * ((FieldOffset / 8) / TypeSizeInBytes);
+  LowAccess.FieldBitStart = BFI.Start;
+  LowAccess.AccessWidth = TypeSizeInBits;
+  // FIXME: This might be wrong!
+  LowAccess.AccessAlignment = 0;
+  LowAccess.TargetBitOffset = 0;
+  LowAccess.TargetBitWidth = LowBits;
+
+  if (NeedsHighAccess) {
+    CGBitFieldInfo::AccessInfo &HighAccess = BFI.getComponent(1);
+    HighAccess.FieldIndex = 0;
+    HighAccess.FieldByteOffset = LowAccess.FieldByteOffset + TypeSizeInBytes;
+    HighAccess.FieldBitStart = 0;
+    HighAccess.AccessWidth = TypeSizeInBits;
+    // FIXME: This might be wrong!
+    HighAccess.AccessAlignment = 0;
+    HighAccess.TargetBitOffset = LowBits;
+    HighAccess.TargetBitWidth = FieldSize - LowBits;
+  }
+
   return BFI;
 }
 
@@ -500,8 +533,13 @@
   for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i)
     RL->BitFields.insert(Builder.LLVMBitFields[i]);
 
-  if (getContext().getLangOptions().DumpRecordLayouts)
+  if (getContext().getLangOptions().DumpRecordLayouts) {
+    llvm::errs() << "\n*** Dumping Record Layout\n";
+    llvm::errs() << "Record: ";
+    D->dump();
+    llvm::errs() << "\nLayout: ";
     RL->dump();
+  }
 
   return RL;
 }
@@ -514,7 +552,7 @@
   for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
          it = BitFields.begin(), ie = BitFields.end();
        it != ie; ++it) {
-    OS << "    ";
+    OS.indent(4);
     it->second.print(OS);
     OS << "\n";
   }
@@ -531,8 +569,30 @@
   OS << " FieldNo:" << FieldNo;
   OS << " Start:" << Start;
   OS << " Size:" << Size;
-  OS << " IsSigned:" << IsSigned;
-  OS << ">";
+  OS << " IsSigned:" << IsSigned << "\n";
+
+  OS.indent(4 + strlen("<CGBitFieldInfo"));
+  OS << " NumComponents:" << getNumComponents();
+  OS << " Components: [";
+  if (getNumComponents()) {
+    OS << "\n";
+    for (unsigned i = 0, e = getNumComponents(); i != e; ++i) {
+      const AccessInfo &AI = getComponent(i);
+      OS.indent(8);
+      OS << "<AccessInfo"
+         << " FieldIndex:" << AI.FieldIndex
+         << " FieldByteOffset:" << AI.FieldByteOffset
+         << " FieldBitStart:" << AI.FieldBitStart
+         << " AccessWidth:" << AI.AccessWidth << "\n";
+      OS.indent(8 + strlen("<AccessInfo"));
+      OS << " AccessAlignment:" << AI.AccessAlignment
+         << " TargetBitOffset:" << AI.TargetBitOffset
+         << " TargetBitWidth:" << AI.TargetBitWidth
+         << ">\n";
+    }
+    OS.indent(4);
+  }
+  OS << "]>";
 }
 
 void CGBitFieldInfo::dump() const {





More information about the cfe-commits mailing list