r235681 - [MS ABI] Fix the preferred alignment of member pointers

David Majnemer david.majnemer at gmail.com
Thu Apr 23 18:25:05 PDT 2015


Author: majnemer
Date: Thu Apr 23 20:25:05 2015
New Revision: 235681

URL: http://llvm.org/viewvc/llvm-project?rev=235681&view=rev
Log:
[MS ABI] Fix the preferred alignment of member pointers

Member pointers in the MS ABI have different alignment depending on
whether they were created on the stack or live in a record.

Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
    cfe/trunk/test/SemaCXX/member-pointer-ms.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=235681&r1=235680&r2=235681&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Apr 23 20:25:05 2015
@@ -1797,11 +1797,16 @@ unsigned ASTContext::getPreferredTypeAli
   TypeInfo TI = getTypeInfo(T);
   unsigned ABIAlign = TI.Align;
 
+  T = T->getBaseElementTypeUnsafe();
+
+  // The preferred alignment of member pointers is that of a pointer.
+  if (T->isMemberPointerType())
+    return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
+
   if (Target->getTriple().getArch() == llvm::Triple::xcore)
     return ABIAlign;  // Never overalign on XCore.
 
   // Double and long long should be naturally aligned if possible.
-  T = T->getBaseElementTypeUnsafe();
   if (const ComplexType *CT = T->getAs<ComplexType>())
     T = CT->getElementType().getTypePtr();
   if (const EnumType *ET = T->getAs<EnumType>())

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=235681&r1=235680&r2=235681&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Apr 23 20:25:05 2015
@@ -1813,8 +1813,7 @@ void CodeGenFunction::EmitFunctionProlog
         ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
       } else {
         // Load scalar value from indirect argument.
-        CharUnits Alignment = getContext().getTypeAlignInChars(Ty);
-        V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty,
+        V = EmitLoadOfScalar(V, false, ArgI.getIndirectAlign(), Ty,
                              Arg->getLocStart());
 
         if (isPromoted)

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp?rev=235681&r1=235680&r2=235681&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp Thu Apr 23 20:25:05 2015
@@ -80,20 +80,20 @@ int UnspecSingle::*us_d_memptr;
 // CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4
 // CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4
 // CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 }
-// CHECK:   { i32 0, i32 -1 }, align 8
+// CHECK:   { i32 0, i32 -1 }, align 4
 // CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 }
-// CHECK:   { i32 0, i32 -1 }, align 8
+// CHECK:   { i32 0, i32 -1 }, align 4
 // CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 }
-// CHECK:   { i32 0, i32 0, i32 -1 }, align 8
+// CHECK:   { i32 0, i32 0, i32 -1 }, align 4
 // CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 }
-// CHECK:   { i32 0, i32 0, i32 -1 }, align 8
+// CHECK:   { i32 0, i32 0, i32 -1 }, align 4
 
 void (Single  ::*s_f_memptr)();
 void (Multiple::*m_f_memptr)();
 void (Virtual ::*v_f_memptr)();
 // CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4
-// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 8
-// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 8
+// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4
 
 // We can define Unspecified after locking in the inheritance model.
 struct Unspecified : Multiple, Virtual {
@@ -115,13 +115,13 @@ void (UnspecSingle::*us_f_mp)() = &Unspe
 // CHECK: @"\01?s_f_mp at Const@@3P8Single@@AEXXZQ2@" =
 // CHECK:   global i8* bitcast ({{.*}} @"\01?foo at Single@@QAEXXZ" to i8*), align 4
 // CHECK: @"\01?m_f_mp at Const@@3P8Multiple@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo at B2@@QAEXXZ" to i8*), i32 4 }, align 8
+// CHECK:   global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo at B2@@QAEXXZ" to i8*), i32 4 }, align 4
 // CHECK: @"\01?v_f_mp at Const@@3P8Virtual@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 8
+// CHECK:   global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
 // CHECK: @"\01?u_f_mp at Const@@3P8Unspecified@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 8
+// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 4
 // CHECK: @"\01?us_f_mp at Const@@3P8UnspecSingle@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 8
+// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo at UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
 }
 
 namespace CastParam {
@@ -143,11 +143,11 @@ void (A::*ptr1)(void *) = (void (A::*)(v
 // Try a reinterpret_cast followed by a memptr conversion.
 void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
 // CHECK: @"\01?ptr2 at CastParam@@3P8C at 1@AEXPAX at ZQ21@" =
-// CHECK:   global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo at A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 8
+// CHECK:   global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo at A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
 
 void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
 // CHECK: @"\01?ptr3 at CastParam@@3P8C at 1@AEXPAX at ZQ21@" =
-// CHECK:   global { i8*, i32 } zeroinitializer, align 8
+// CHECK:   global { i8*, i32 } zeroinitializer, align 4
 
 struct D : C {
   virtual void isPolymorphic();
@@ -180,23 +180,23 @@ void EmitNonVirtualMemberPointers() {
   void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
 // CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
 // CHECK:   alloca i8*, align 4
-// CHECK:   alloca { i8*, i32 }, align 8
-// CHECK:   alloca { i8*, i32, i32 }, align 8
-// CHECK:   alloca { i8*, i32, i32, i32 }, align 8
+// CHECK:   alloca { i8*, i32 }, align 4
+// CHECK:   alloca { i8*, i32, i32 }, align 4
+// CHECK:   alloca { i8*, i32, i32, i32 }, align 4
 // CHECK:   store i8* bitcast (void (%{{.*}}*)* @"\01?foo at Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
 // CHECK:   store { i8*, i32 }
 // CHECK:     { i8* bitcast (void (%{{.*}}*)* @"\01?foo at Multiple@@QAEXXZ" to i8*), i32 0 },
-// CHECK:     { i8*, i32 }* %{{.*}}, align 8
+// CHECK:     { i8*, i32 }* %{{.*}}, align 4
 // CHECK:   store { i8*, i32, i32 }
 // CHECK:     { i8* bitcast (void (%{{.*}}*)* @"\01?foo at Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
-// CHECK:     { i8*, i32, i32 }* %{{.*}}, align 8
+// CHECK:     { i8*, i32, i32 }* %{{.*}}, align 4
 // CHECK:   store { i8*, i32, i32, i32 }
 // CHECK:     { i8* bitcast (void (%{{.*}}*)* @"\01?foo at Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 },
-// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 8
+// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 4
 // CHECK:   store { i8*, i32, i32, i32 }
 // CHECK:     { i8* bitcast (void (%{{.*}}*)* @"\01?foo at UnspecWithVBPtr@@QAEXXZ" to i8*),
 // CHECK:       i32 0, i32 4, i32 0 },
-// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 8
+// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 4
 // CHECK:   ret void
 // CHECK: }
 }
@@ -243,9 +243,9 @@ void polymorphicMemPtrs() {
 bool nullTestDataUnspecified(int Unspecified::*mp) {
   return mp;
 // CHECK: define zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H at Z"{{.*}} {
-// CHECK:   %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 8
-// CHECK:   store { i32, i32, i32 } {{.*}} align 8
-// CHECK:   %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 8
+// CHECK:   %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:   store { i32, i32, i32 } {{.*}} align 4
+// CHECK:   %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
 // CHECK:   %[[mp0:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 0
 // CHECK:   %[[cmp0:.*]] = icmp ne i32 %[[mp0]], 0
 // CHECK:   %[[mp1:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 1
@@ -265,9 +265,9 @@ bool nullTestDataUnspecified(int Unspeci
 bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
   return mp;
 // CHECK: define zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ at Z"{{.*}} {
-// CHECK:   %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 8
-// CHECK:   store { i8*, i32, i32, i32 } {{.*}} align 8
-// CHECK:   %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 8
+// CHECK:   %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:   store { i8*, i32, i32, i32 } {{.*}} align 4
+// CHECK:   %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
 // CHECK:   %[[mp0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[mp]], 0
 // CHECK:   %[[cmp0:.*]] = icmp ne i8* %[[mp0]], null
 // CHECK:   ret i1 %[[cmp0]]
@@ -280,7 +280,7 @@ int loadDataMemberPointerVirtual(Virtual
 // data pointer.
 // CHECK: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1 at H@Z"{{.*}} {
 // CHECK:   %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
-// CHECK:   %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 8
+// CHECK:   %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 4
 // CHECK:   %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
 // CHECK:   %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1
 // CHECK:   %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8*
@@ -309,7 +309,7 @@ int loadDataMemberPointerUnspecified(Uns
 // data pointer.
 // CHECK: define i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1 at H@Z"{{.*}} {
 // CHECK:   %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
-// CHECK:   %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 8
+// CHECK:   %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
 // CHECK:   %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
 // CHECK:   %[[memptr1:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 1
 // CHECK:   %[[memptr2:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 2
@@ -509,7 +509,7 @@ void (B2::*convertMultipleFuncToB2(void
 //
 // CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ at Z"{{.*}} {
 // CHECK:   store
-// CHECK:   %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 8
+// CHECK:   %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 4
 // CHECK:   extractvalue { i8*, i32 } %[[src]], 0
 // CHECK:   icmp ne i8* %{{.*}}, null
 // CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
@@ -534,7 +534,7 @@ void (D::*convertCToD(void (C::*mp)()))(
   return mp;
 // CHECK: define void @"\01?convertCToD at Test1@@YAP8D at 1@AEXXZP8C at 1@AEXXZ at Z"{{.*}} {
 // CHECK:   store
-// CHECK:   load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 8
+// CHECK:   load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 4
 // CHECK:   extractvalue { i8*, i32, i32 } %{{.*}}, 0
 // CHECK:   icmp ne i8* %{{.*}}, null
 // CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}

Modified: cfe/trunk/test/SemaCXX/member-pointer-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer-ms.cpp?rev=235681&r1=235680&r2=235681&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer-ms.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer-ms.cpp Thu Apr 23 20:25:05 2015
@@ -93,15 +93,15 @@ static_assert(sizeof(void (IncSingle::*)
 static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
 static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, "");
 
-static_assert(__alignof(int IncSingle::*)        == kSingleDataAlign, "");
-static_assert(__alignof(int IncMultiple::*)      == kMultipleDataAlign, "");
-static_assert(__alignof(int IncVirtual::*)       == kVirtualDataAlign, "");
-static_assert(__alignof(void (IncSingle::*)())   == kSingleFunctionAlign, "");
-static_assert(__alignof(void (IncMultiple::*)()) == kMultipleFunctionAlign, "");
-static_assert(__alignof(void (IncVirtual::*)())  == kVirtualFunctionAlign, "");
+static_assert(__alignof(int IncSingle::*)        == __alignof(void *), "");
+static_assert(__alignof(int IncMultiple::*)      == __alignof(void *), "");
+static_assert(__alignof(int IncVirtual::*)       == __alignof(void *), "");
+static_assert(__alignof(void (IncSingle::*)())   == __alignof(void *), "");
+static_assert(__alignof(void (IncMultiple::*)()) == __alignof(void *), "");
+static_assert(__alignof(void (IncVirtual::*)())  == __alignof(void *), "");
 
 // An incomplete type with an unspecified inheritance model seems to take one
-// more slot than virtual.  It's not clear what it's used for yet.
+// more slot than virtual.
 class IncUnspecified;
 static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
 static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");





More information about the cfe-commits mailing list