[PATCH] [ms-cxxabi] Move MS inheritance model calculation into MemberPointerType
Reid Kleckner
rnk at google.com
Thu Mar 28 14:29:19 PDT 2013
Hi rjmccall,
This makes it possible to share code between lib/AST/MicrosoftCXXABI.cpp
and lib/CodeGen/MicrosoftCXXABI.cpp. No functionality change.
Also adds comments about the layout of the member pointer structs as I
currently understand them.
http://llvm-reviews.chandlerc.com/D590
Files:
include/clang/AST/Type.h
lib/AST/MicrosoftCXXABI.cpp
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -2092,6 +2092,14 @@
}
};
+/// The inheritance model to use for this member pointer.
+enum MSInheritanceModel {
+ IHM_Single,
+ IHM_Multiple,
+ IHM_Virtual,
+ IHM_Unspecified
+};
+
/// MemberPointerType - C++ 8.3.3 - Pointers to members
///
class MemberPointerType : public Type, public llvm::FoldingSetNode {
@@ -2127,6 +2135,13 @@
return !PointeeType->isFunctionProtoType();
}
+ /// Returns the inheritance model used for this member pointer.
+ MSInheritanceModel getMSInheritanceModel() const;
+
+ /// Returns the number of pointer and integer slots used to represent this
+ /// member pointer in the MS C++ ABI.
+ std::pair<unsigned, unsigned> getMSMemberPointerSlots() const;
+
const Type *getClass() const { return Class; }
bool isSugared() const { return false; }
Index: lib/AST/MicrosoftCXXABI.cpp
===================================================================
--- lib/AST/MicrosoftCXXABI.cpp
+++ lib/AST/MicrosoftCXXABI.cpp
@@ -57,7 +57,7 @@
// getNumBases() seems to only give us the number of direct bases, and not the
// total. This function tells us if we inherit from anybody that uses MI, or if
// we have a non-primary base class, which uses the multiple inheritance model.
-static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
+bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
while (RD->getNumBases() > 0) {
if (RD->getNumBases() > 1)
return true;
@@ -70,60 +70,107 @@
return false;
}
-std::pair<uint64_t, unsigned>
-MicrosoftCXXABI::getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const {
- const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
- const TargetInfo &Target = Context.getTargetInfo();
-
- assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
- Target.getTriple().getArch() == llvm::Triple::x86_64);
+MSInheritanceModel MSInheritanceAttrToModel(attr::Kind Kind) {
+ switch (Kind) {
+ default: llvm_unreachable("expected MS inheritance attribute");
+ case attr::SingleInheritance: return IHM_Single;
+ case attr::MultipleInheritance: return IHM_Multiple;
+ case attr::VirtualInheritance: return IHM_Virtual;
+ case attr::UnspecifiedInheritance: return IHM_Unspecified;
+ }
+}
+MSInheritanceModel MemberPointerType::getMSInheritanceModel() const {
+ const CXXRecordDecl *RD = this->getClass()->getAsCXXRecordDecl();
Attr *IA = RD->getAttr<MSInheritanceAttr>();
- attr::Kind Inheritance;
- if (IA) {
- Inheritance = IA->getKind();
- } else if (RD->getNumVBases() > 0) {
- Inheritance = attr::VirtualInheritance;
- } else if (MPT->getPointeeType()->isFunctionType() &&
- usesMultipleInheritanceModel(RD)) {
- Inheritance = attr::MultipleInheritance;
- } else {
- Inheritance = attr::SingleInheritance;
- }
+ if (IA)
+ return MSInheritanceAttrToModel(IA->getKind());
+ // If there was no explicit attribute, the record must be defined already, and
+ // we can figure out the inheritance model from its other properties.
+ if (RD->getNumVBases() > 0)
+ return IHM_Virtual;
+ if (this->getPointeeType()->isFunctionType() &&
+ usesMultipleInheritanceModel(RD))
+ return IHM_Multiple;
+ return IHM_Single;
+}
- unsigned PtrSize = Target.getPointerWidth(0);
- unsigned IntSize = Target.getIntWidth();
- uint64_t Width;
- unsigned Align;
- if (MPT->getPointeeType()->isFunctionType()) {
+// Returns the number of pointer and integer slots used to represent a member
+// pointer in the MS C++ ABI.
+//
+// Member function pointers have the following general form; however, fields
+// are dropped as permitted (under the MSVC interpretation) by the inheritance
+// model of the actual class.
+//
+// struct {
+// // A pointer to the member function to call. If the member function is
+// // virtual, this will be a thunk that forwards to the appropriate vftable
+// // slot.
+// void *FunctionPointerOrVirtualThunk;
+//
+// // An offset to add to the address of the vbtable pointer after (possibly)
+// // selecting the virtual base but before resolving and calling the function.
+// // Only needed if the class has any virtual bases or bases at a non-zero
+// // offset.
+// int NonVirtualBaseAdjustment;
+//
+// // An offset within the vb-table that selects the virtual base containing
+// // the member. Loading from this offset produces a new offset that is
+// // added to the address of the vb-table pointer to produce the base.
+// int VirtualBaseAdjustmentOffset;
+//
+// // The offset of the vb-table pointer within the object. Only needed for
+// // incomplete types.
+// int VBTableOffset;
+// };
+std::pair<unsigned, unsigned> MemberPointerType::getMSMemberPointerSlots() const {
+ MSInheritanceModel Inheritance = this->getMSInheritanceModel();
+ unsigned Ptrs;
+ unsigned Ints = 0;
+ if (this->isMemberFunctionPointer()) {
// Member function pointers are a struct of a function pointer followed by a
// variable number of ints depending on the inheritance model used. The
// function pointer is a real function if it is non-virtual and a vftable
// slot thunk if it is virtual. The ints select the object base passed for
// the 'this' pointer.
- Align = Target.getPointerAlign(0);
+ Ptrs = 1; // First slot is always a function pointer.
switch (Inheritance) {
- case attr::SingleInheritance: Width = PtrSize; break;
- case attr::MultipleInheritance: Width = PtrSize + 1 * IntSize; break;
- case attr::VirtualInheritance: Width = PtrSize + 2 * IntSize; break;
- case attr::UnspecifiedInheritance: Width = PtrSize + 3 * IntSize; break;
default: llvm_unreachable("unknown inheritance model");
+ case IHM_Unspecified: ++Ints; // VBTableOffset
+ case IHM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset
+ case IHM_Multiple: ++Ints; // NonVirtualBaseAdjustment
+ case IHM_Single: break; // Nothing
}
} else {
// Data pointers are an aggregate of ints. The first int is an offset
// followed by vbtable-related offsets.
- Align = Target.getIntAlign();
+ Ptrs = 0;
switch (Inheritance) {
- case attr::SingleInheritance: // Same as multiple inheritance.
- case attr::MultipleInheritance: Width = 1 * IntSize; break;
- case attr::VirtualInheritance: Width = 2 * IntSize; break;
- case attr::UnspecifiedInheritance: Width = 3 * IntSize; break;
default: llvm_unreachable("unknown inheritance model");
+ case IHM_Unspecified: ++Ints; // VBTableOffset
+ case IHM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset
+ case IHM_Multiple: // Nothing
+ case IHM_Single: ++Ints; // Field offset
}
}
- Width = llvm::RoundUpToAlignment(Width, Align);
+ return std::make_pair(Ptrs, Ints);
+}
- // FIXME: Verify that our alignment matches MSVC.
+std::pair<uint64_t, unsigned>
+MicrosoftCXXABI::getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const {
+ const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ const TargetInfo &Target = Context.getTargetInfo();
+ assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
+ Target.getTriple().getArch() == llvm::Triple::x86_64);
+ unsigned Ptrs, Ints;
+ llvm::tie(Ptrs, Ints) = MPT->getMSMemberPointerSlots();
+ // The nominal struct is laid out with pointers followed by ints and aligned
+ // to a pointer width if any are present and an int width otherwise.
+ unsigned PtrSize = Target.getPointerWidth(0);
+ unsigned IntSize = Target.getIntWidth();
+ uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
+ unsigned Align = Ptrs > 0 ? Target.getPointerAlign(0) : Target.getIntAlign();
+ Width = llvm::RoundUpToAlignment(Width, Align);
return std::make_pair(Width, Align);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D590.1.patch
Type: text/x-patch
Size: 8052 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130328/30427741/attachment.bin>
More information about the cfe-commits
mailing list