diff options
author | Warren Hunt <whunt@google.com> | 2014-01-09 23:51:31 +0000 |
---|---|---|
committer | Warren Hunt <whunt@google.com> | 2014-01-09 23:51:31 +0000 |
commit | 640015cbc3c371ad196b9252ca85e59436ddf17e (patch) | |
tree | a288d0e15330fa06f9f783079de74e9a51038e3c /clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | |
parent | a4bb4b9f0ba15f6d5c4e37a5db4f72a6388a6a2f (diff) | |
download | bcm5719-llvm-640015cbc3c371ad196b9252ca85e59436ddf17e.tar.gz bcm5719-llvm-640015cbc3c371ad196b9252ca85e59436ddf17e.zip |
[ms-abi] Fixing CGRecordLayoutBuilder w.r.t. MS NonVirutalBase Layout
The MS abi lays out *all* non-virtual bases with leading vfptrs before
laying out non-virutal bases without vfptrs. This guarantees that the
primary base is laid out first. r198818 fixed RecordLayoutBuilder to
produce compatiable layouts. This patch fixes CGRecordLayoutBuilder to
be able to consume those layouts and produce meaningful output without
tripping any asserts about assumed incoming layout.
A test case is included that shows CGRecordLayoutBuilder in fact
produces output in the compatiable order.
llvm-svn: 198900
Diffstat (limited to 'clang/lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index c3338a17b36..3aa1f81c737 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -144,6 +144,11 @@ private: bool LayoutNonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout); + /// MSLayoutNonVirtualBases - 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 @@ CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD, } bool +CGRecordLayoutBuilder::MSLayoutNonVirtualBases(const CXXRecordDecl *RD, + const ASTRecordLayout &Layout) { + // 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 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; + } + + // 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 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { 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; |