Author: rnk Date: Wed Aug 31 11:11:43 2016 New Revision: 280255 URL: http://llvm.org/viewvc/llvm-project?rev=280255&view=rev Log: [codeview] Pass through vftable shape information
The shape is really just the number of methods in the vftable, since we don't support 16 bit far calls. All calls are near. Encode this number in the size of the artificial __vtbl_ptr_type DIDerivedType that we generate. For DWARF, this will be a normal pointer, but for codeview this will be a wide pointer that gets pattern matched into a VFTableShape record. Insert this type into the element list of all dynamic classes when emitting CodeView, so that the backend can emit the shape even if the vptr lives in a primary base class. Fixes PR28150 Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/lib/CodeGen/CGDebugInfo.h cfe/trunk/test/CodeGenCXX/debug-info-ms-abi.cpp Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=280255&r1=280254&r2=280255&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed Aug 31 11:11:43 2016 @@ -1549,22 +1549,49 @@ StringRef CGDebugInfo::getVTableName(con } void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys) { - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); + SmallVectorImpl<llvm::Metadata *> &EltTys, + llvm::DICompositeType *RecordTy) { + // If this class is not dynamic then there is not any vtable info to collect. + if (!RD->isDynamicClass()) + return; + + // CodeView needs to know how large the vtable of every dynamic class is, so + // emit a special named pointer type into the element list. The vptr type + // points to this type as well. + llvm::DIType *VPtrTy = nullptr; + bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView && + CGM.getTarget().getCXXABI().isMicrosoft(); + if (NeedVTableShape) { + uint64_t PtrWidth = + CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); + const VTableLayout &VFTLayout = + CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero()); + unsigned VSlotCount = + VFTLayout.getNumVTableComponents() - CGM.getLangOpts().RTTIData; + unsigned VTableWidth = PtrWidth * VSlotCount; + + // Create a very wide void* type and insert it directly in the element list. + llvm::DIType *VTableType = + DBuilder.createPointerType(nullptr, VTableWidth, 0, "__vtbl_ptr_type"); + EltTys.push_back(VTableType); - // If there is a primary base then it will hold vtable info. + // The vptr is a pointer to this special vtable type. + VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth); + } + + // If there is a primary base then the artificial vptr member lives there. + const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); if (RL.getPrimaryBase()) return; - // If this class is not dynamic then there is not any vtable info to collect. - if (!RD->isDynamicClass()) - return; + if (!VPtrTy) + VPtrTy = getOrCreateVTablePtrType(Unit); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType *VPTR = DBuilder.createMemberType( + llvm::DIType *VPtrMember = DBuilder.createMemberType( Unit, getVTableName(RD), Unit, 0, Size, 0, 0, - llvm::DINode::FlagArtificial, getOrCreateVTablePtrType(Unit)); - EltTys.push_back(VPTR); + llvm::DINode::FlagArtificial, VPtrTy); + EltTys.push_back(VPtrMember); } llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, @@ -1761,7 +1788,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDef const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD); if (CXXDecl) { CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl); - CollectVTableInfo(CXXDecl, DefUnit, EltTys); + CollectVTableInfo(CXXDecl, DefUnit, EltTys, FwdDecl); } // Collect data fields (including static variables and any initializers). Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=280255&r1=280254&r2=280255&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Wed Aug 31 11:11:43 2016 @@ -264,7 +264,8 @@ class CGDebugInfo { /// If the C++ class has vtable info then insert appropriate debug /// info entry in EltTys vector. void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F, - SmallVectorImpl<llvm::Metadata *> &EltTys); + SmallVectorImpl<llvm::Metadata *> &EltTys, + llvm::DICompositeType *RecordTy); /// @} /// Create a new lexical block node and push it on the stack. Modified: cfe/trunk/test/CodeGenCXX/debug-info-ms-abi.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-ms-abi.cpp?rev=280255&r1=280254&r2=280255&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/debug-info-ms-abi.cpp (original) +++ cfe/trunk/test/CodeGenCXX/debug-info-ms-abi.cpp Wed Aug 31 11:11:43 2016 @@ -15,7 +15,14 @@ Foo::Nested n; // CHECK-SAME: elements: ![[elements:[0-9]+]] // CHECK-SAME: identifier: ".?AUFoo@@" -// CHECK: ![[elements]] = !{![[vptr:[0-9]+]], ![[Nested:[0-9]+]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]]} +// CHECK: ![[elements]] = !{![[vshape:[0-9]+]], ![[vptr:[0-9]+]], ![[Nested:[0-9]+]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]]} + +// CHECK: ![[vshape]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: null, size: 96) + +// CHECK: ![[vptr]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$Foo", +// CHECK-SAME: baseType: ![[vptr_ty:[0-9]+]], + +// CHECK: ![[vptr_ty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[vshape]], size: 32 // CHECK: ![[Nested]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", // CHECK-SAME: identifier: ".?AUNested@Foo@@" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits