r176163 - Use the correct alignment for POD-member memcpys where the first field is a

Lang Hames lhames at gmail.com
Tue Feb 26 20:14:50 PST 2013


Author: lhames
Date: Tue Feb 26 22:14:49 2013
New Revision: 176163

URL: http://llvm.org/viewvc/llvm-project?rev=176163&view=rev
Log:
Use the correct alignment for POD-member memcpys where the first field is a
bitfield. CGBitField::StorageAlignment holds the alignment in chars, but
emitMemcpy had been treating it as if it were held in bits, leading to
underaligned memcpys.

Related to PR15348.

Thanks very much to Chandler for the diagnosis.


Modified:
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/test/CodeGenCXX/pod-member-memcpys.cpp

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=176163&r1=176162&r2=176163&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Feb 26 22:14:49 2013
@@ -788,19 +788,22 @@ namespace {
         return;
       }
 
-      unsigned FirstFieldAlign = ~0U; // Set to invalid.
+      CharUnits Alignment;
 
       if (FirstField->isBitField()) {
         const CGRecordLayout &RL =
           CGF.getTypes().getCGRecordLayout(FirstField->getParent());
         const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
-        FirstFieldAlign = BFInfo.StorageAlignment;
-      } else
-        FirstFieldAlign = CGF.getContext().getTypeAlign(FirstField->getType());
+        Alignment = CharUnits::fromQuantity(BFInfo.StorageAlignment);
+      } else {
+        unsigned AlignBits =
+          CGF.getContext().getTypeAlign(FirstField->getType());
+        Alignment = CGF.getContext().toCharUnitsFromBits(AlignBits);
+      }
+
+      assert((CGF.getContext().toCharUnitsFromBits(FirstFieldOffset) %
+              Alignment) == 0 && "Bad field alignment.");
 
-      assert(FirstFieldOffset % FirstFieldAlign == 0 && "Bad field alignment.");
-      CharUnits Alignment =
-        CGF.getContext().toCharUnitsFromBits(FirstFieldAlign);
       CharUnits MemcpySize = getMemcpySize();
       QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
       llvm::Value *ThisPtr = CGF.LoadCXXThis();

Modified: cfe/trunk/test/CodeGenCXX/pod-member-memcpys.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pod-member-memcpys.cpp?rev=176163&r1=176162&r2=176163&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pod-member-memcpys.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pod-member-memcpys.cpp Tue Feb 26 22:14:49 2013
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++03 -fexceptions -fcxx-exceptions -O1 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -std=c++03 -O0 -o - %s | FileCheck --check-prefix=CHECK-2 %s
 
 struct POD {
   int w, x, y, z;
@@ -60,6 +61,12 @@ struct BitfieldMember {
   int z : 6;
 };
 
+struct BitfieldMember2 {
+  unsigned a : 1;
+  unsigned b, c, d;
+  NonPOD np;
+};
+
 struct InnerClassMember {
   struct {
     int a, b, c, d;
@@ -152,6 +159,7 @@ CALL_AO(InnerClassMember)
 
 #define CALL_CC(T) T callCC##T(const T& b) { return b; }
 
+CALL_CC(BitfieldMember2)
 CALL_CC(ReferenceMember)
 CALL_CC(InnerClassMember)
 CALL_CC(BitfieldMember)
@@ -220,3 +228,9 @@ CALL_CC(Basic)
 // CHECK: tail call void @_ZN6NonPODC1ERKS_
 // CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
 // CHECK: ret void
+
+// BitfieldMember2 copy-constructor:
+// CHECK-2: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2*)
+// CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false)
+// CHECK-2: call void @_ZN6NonPODC1ERKS_
+// CHECK-2: ret void





More information about the cfe-commits mailing list