[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