[PATCH] Support MS Non-Virtual Base Placement Rules in CGRecordLayoutBuilder

David Majnemer david.majnemer at gmail.com
Thu Jan 9 09:59:38 PST 2014


majnemer added you to the CC list for the revision "Support MS Non-Virtual Base Placement Rules in CGRecordLayoutBuilder".

Hi rnk, majnemer, rsmith,

Adds a case to CGRecordLayoutBuilder to understand how the ms-abi lays out non-virtual bases.  This behavior is already supported by RecordLayoutBuilder, but invoking the behavior would cause an assertion to trip in CGRecordLayoutBuilder when it didn't recognize the layout.

http://llvm-reviews.chandlerc.com/D2524

Files:
  lib/CodeGen/CGRecordLayoutBuilder.cpp
  test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp

Index: lib/CodeGen/CGRecordLayoutBuilder.cpp
===================================================================
--- lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -144,6 +144,11 @@
   bool LayoutNonVirtualBases(const CXXRecordDecl *RD, 
                              const ASTRecordLayout &Layout);
 
+  /// LayoutNonVirtualBases - layout the virtual bases of a record decl,
+  /// like MSVC.
+  bool MSLayoutNonVirtualBases(const CXXRecordDecl *RD, 
+                               const ASTRecordLayout &Layout);
+
   /// ComputeNonVirtualBaseType - Compute the non-virtual base field types.
   bool ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
   
@@ -708,6 +713,72 @@
 }
 
 bool
+CGRecordLayoutBuilder::MSLayoutNonVirtualBases(const CXXRecordDecl *RD,
+                                               const ASTRecordLayout &Layout) {
+  // Layout the non-virtual bases that have leading vfptrs.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+    if (I->isVirtual())
+      continue;
+    const CXXRecordDecl *BaseDecl = 
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+    const ASTRecordLayout &BaseLayout
+      = Types.getContext().getASTRecordLayout(BaseDecl);
+
+    if (!BaseLayout.hasExtendableVFPtr())
+      continue;
+
+    if (!LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)))
+      return false;
+  }
+
+  // Add a vfptr if the layout says to do so.
+  if (Layout.hasOwnVFPtr()) {
+    llvm::Type *FunctionType =
+      llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()),
+                              /*isVarArg=*/true);
+    llvm::Type *VTableTy = FunctionType->getPointerTo();
+
+    if (getTypeAlignment(VTableTy) > Alignment) {
+      // FIXME: Should we allow this to happen in Sema?
+      assert(!Packed && "Alignment is wrong even with packed struct!");
+      return false;
+    }
+
+    assert(NextFieldOffset.isZero() &&
+           "VTable pointer must come first!");
+    AppendField(CharUnits::Zero(), VTableTy->getPointerTo());
+  }
+
+  // Layout the non-virtual bases that don't have leading vfptrs.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+    if (I->isVirtual())
+      continue;
+    const CXXRecordDecl *BaseDecl = 
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+    const ASTRecordLayout &BaseLayout
+      = Types.getContext().getASTRecordLayout(BaseDecl);
+
+    if (BaseLayout.hasExtendableVFPtr())
+      continue;
+
+    if (!LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)))
+      return false;
+  }
+
+  // Add a vb-table pointer if the layout insists.
+  if (Layout.hasOwnVBPtr()) {
+    CharUnits VBPtrOffset = Layout.getVBPtrOffset();
+    llvm::Type *Vbptr = llvm::Type::getInt32PtrTy(Types.getLLVMContext());
+    AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr));
+    AppendField(VBPtrOffset, Vbptr);
+  }
+
+  return true;
+}
+
+bool
 CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
   const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);
 
@@ -755,7 +826,10 @@
 
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
   if (RD)
-    if (!LayoutNonVirtualBases(RD, Layout))
+    if (Types.getTarget().getCXXABI().isMicrosoft()) {
+      if (!MSLayoutNonVirtualBases(RD, Layout))
+        return false;
+    } else if (!LayoutNonVirtualBases(RD, Layout))
       return false;
 
   unsigned FieldNo = 0;
Index: test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=i686-pc-win32 -o - %s  2>/dev/null | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=x86_64-pc-win32 -o - %s  2>/dev/null | FileCheck %s
+
+struct C0 { int a; };
+struct C1 { int a; virtual void C1M() {} };
+struct C2 { int a; virtual void C2M() {} };
+struct C3 : C0, C1, C2 {} a;
+
+// Check to see that both C1 and C2 get laid out before C0 does.
+// CHECK: %struct.C3 = type { %struct.C1, %struct.C2, %struct.C0 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2524.1.patch
Type: text/x-patch
Size: 4367 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140109/50716f48/attachment.bin>


More information about the cfe-commits mailing list