]> granicus.if.org Git - clang/commitdiff
improve support for big endian targets, fixing PR8171, patch
authorChris Lattner <sabre@nondot.org>
Thu, 17 Feb 2011 22:09:58 +0000 (22:09 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 17 Feb 2011 22:09:58 +0000 (22:09 +0000)
by Heikki Kultala!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125784 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGRecordLayoutBuilder.cpp

index 1f222a2bd1df08c483152859f2b8754737f0f15d..40d7b6c32e4b02e9a3df9c7c6c975f4d90048ba5 100644 (file)
@@ -231,7 +231,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
 
     if (CGM.getTargetData().isBigEndian()) {
       // We want the high bits.
-      Tmp = FieldValue.lshr(Tmp.getBitWidth() - 8).trunc(8);
+      Tmp = FieldValue.lshr(FieldValue.getBitWidth() - 8).trunc(8);
     } else {
       // We want the low bits.
       Tmp = FieldValue.trunc(8);
index 7704091b5bb5f8c23c0e2658eb1f3a56d20dd03c..4b19aefcf9c4e7d5c1f525c6f63e06b390839bf4 100644 (file)
@@ -225,6 +225,12 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
     FieldSize = TypeSizeInBits;
   }
 
+  // in big-endian machines the first fields are in higher bit positions,
+  // so revert the offset. The byte offsets are reversed(back) later.
+  if (Types.getTargetData().isBigEndian()) {
+    FieldOffset = ((ContainingTypeSizeInBits)-FieldOffset-FieldSize);
+  }
+
   // Compute the access components. The policy we use is to start by attempting
   // to access using the width of the bit-field type itself and to always access
   // at aligned indices of that type. If such an access would fail because it
@@ -232,7 +238,6 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
   // power of two and retry. The current algorithm assumes pow2 sized types,
   // although this is easy to fix.
   //
-  // FIXME: This algorithm is wrong on big-endian systems, I think.
   assert(llvm::isPowerOf2_32(TypeSizeInBits) && "Unexpected type size!");
   CGBitFieldInfo::AccessInfo Components[3];
   unsigned NumComponents = 0;
@@ -280,7 +285,15 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
     // FIXME: We still follow the old access pattern of only using the field
     // byte offset. We should switch this once we fix the struct layout to be
     // pretty.
-    AI.FieldByteOffset = AccessStart / 8;
+
+    // on big-endian machines we reverted the bit offset because first fields are
+    // in higher bits. But this also reverts the bytes, so fix this here by reverting
+    // the byte offset on big-endian machines.
+    if (Types.getTargetData().isBigEndian()) {
+      AI.FieldByteOffset = (ContainingTypeSizeInBits - AccessStart - AccessWidth )/8;
+    } else {
+      AI.FieldByteOffset = AccessStart / 8;
+    }
     AI.FieldBitStart = AccessBitsInFieldStart - AccessStart;
     AI.AccessWidth = AccessWidth;
     AI.AccessAlignment = llvm::MinAlign(ContainingTypeAlign, AccessStart) / 8;