1 //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This provides C++ AST support targeting the Microsoft Visual C++
13 //===----------------------------------------------------------------------===//
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/Attr.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/MangleNumberingContext.h"
20 #include "clang/AST/RecordLayout.h"
21 #include "clang/AST/Type.h"
22 #include "clang/Basic/TargetInfo.h"
24 using namespace clang
;
28 /// \brief Numbers things which need to correspond across multiple TUs.
29 /// Typically these are things like static locals, lambdas, or blocks.
30 class MicrosoftNumberingContext
: public MangleNumberingContext
{
31 llvm::DenseMap
<const Type
*, unsigned> ManglingNumbers
;
32 unsigned LambdaManglingNumber
;
33 unsigned StaticLocalNumber
;
36 MicrosoftNumberingContext()
37 : MangleNumberingContext(), LambdaManglingNumber(0),
38 StaticLocalNumber(0) {}
40 unsigned getManglingNumber(const CXXMethodDecl
*CallOperator
) override
{
41 return ++LambdaManglingNumber
;
44 unsigned getManglingNumber(const BlockDecl
*BD
) override
{
45 const Type
*Ty
= nullptr;
46 return ++ManglingNumbers
[Ty
];
49 unsigned getStaticLocalNumber(const VarDecl
*VD
) override
{
50 return ++StaticLocalNumber
;
53 unsigned getManglingNumber(const VarDecl
*VD
,
54 unsigned MSLocalManglingNumber
) override
{
55 return MSLocalManglingNumber
;
58 unsigned getManglingNumber(const TagDecl
*TD
,
59 unsigned MSLocalManglingNumber
) override
{
60 return MSLocalManglingNumber
;
64 class MicrosoftCXXABI
: public CXXABI
{
67 MicrosoftCXXABI(ASTContext
&Ctx
) : Context(Ctx
) { }
69 std::pair
<uint64_t, unsigned>
70 getMemberPointerWidthAndAlign(const MemberPointerType
*MPT
) const override
;
72 CallingConv
getDefaultMethodCallConv(bool isVariadic
) const override
{
74 Context
.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
)
75 return CC_X86ThisCall
;
79 bool isNearlyEmpty(const CXXRecordDecl
*RD
) const override
{
80 // FIXME: Audit the corners
81 if (!RD
->isDynamicClass())
84 const ASTRecordLayout
&Layout
= Context
.getASTRecordLayout(RD
);
86 // In the Microsoft ABI, classes can have one or two vtable pointers.
87 CharUnits PointerSize
=
88 Context
.toCharUnitsFromBits(Context
.getTargetInfo().getPointerWidth(0));
89 return Layout
.getNonVirtualSize() == PointerSize
||
90 Layout
.getNonVirtualSize() == PointerSize
* 2;
93 MangleNumberingContext
*createMangleNumberingContext() const override
{
94 return new MicrosoftNumberingContext();
99 // getNumBases() seems to only give us the number of direct bases, and not the
100 // total. This function tells us if we inherit from anybody that uses MI, or if
101 // we have a non-primary base class, which uses the multiple inheritance model.
102 static bool usesMultipleInheritanceModel(const CXXRecordDecl
*RD
) {
103 while (RD
->getNumBases() > 0) {
104 if (RD
->getNumBases() > 1)
106 assert(RD
->getNumBases() == 1);
107 const CXXRecordDecl
*Base
=
108 RD
->bases_begin()->getType()->getAsCXXRecordDecl();
109 if (RD
->isPolymorphic() && !Base
->isPolymorphic())
116 MSInheritanceAttr::Spelling
CXXRecordDecl::calculateInheritanceModel() const {
117 if (!hasDefinition() || isParsingBaseSpecifiers())
118 return MSInheritanceAttr::Keyword_unspecified_inheritance
;
119 if (getNumVBases() > 0)
120 return MSInheritanceAttr::Keyword_virtual_inheritance
;
121 if (usesMultipleInheritanceModel(this))
122 return MSInheritanceAttr::Keyword_multiple_inheritance
;
123 return MSInheritanceAttr::Keyword_single_inheritance
;
126 MSInheritanceAttr::Spelling
127 CXXRecordDecl::getMSInheritanceModel() const {
128 MSInheritanceAttr
*IA
= getAttr
<MSInheritanceAttr
>();
129 assert(IA
&& "Expected MSInheritanceAttr on the CXXRecordDecl!");
130 return IA
->getSemanticSpelling();
133 MSVtorDispAttr::Mode
CXXRecordDecl::getMSVtorDispMode() const {
134 if (MSVtorDispAttr
*VDA
= getAttr
<MSVtorDispAttr
>())
135 return VDA
->getVtorDispMode();
136 return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode
);
139 // Returns the number of pointer and integer slots used to represent a member
140 // pointer in the MS C++ ABI.
142 // Member function pointers have the following general form; however, fields
143 // are dropped as permitted (under the MSVC interpretation) by the inheritance
144 // model of the actual class.
147 // // A pointer to the member function to call. If the member function is
148 // // virtual, this will be a thunk that forwards to the appropriate vftable
150 // void *FunctionPointerOrVirtualThunk;
152 // // An offset to add to the address of the vbtable pointer after (possibly)
153 // // selecting the virtual base but before resolving and calling the function.
154 // // Only needed if the class has any virtual bases or bases at a non-zero
156 // int NonVirtualBaseAdjustment;
158 // // The offset of the vb-table pointer within the object. Only needed for
159 // // incomplete types.
162 // // An offset within the vb-table that selects the virtual base containing
163 // // the member. Loading from this offset produces a new offset that is
164 // // added to the address of the vb-table pointer to produce the base.
165 // int VirtualBaseAdjustmentOffset;
167 static std::pair
<unsigned, unsigned>
168 getMSMemberPointerSlots(const MemberPointerType
*MPT
) {
169 const CXXRecordDecl
*RD
= MPT
->getMostRecentCXXRecordDecl();
170 MSInheritanceAttr::Spelling Inheritance
= RD
->getMSInheritanceModel();
173 if (MPT
->isMemberFunctionPointer())
177 if (MSInheritanceAttr::hasNVOffsetField(MPT
->isMemberFunctionPointer(),
180 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance
))
182 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance
))
184 return std::make_pair(Ptrs
, Ints
);
187 std::pair
<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
188 const MemberPointerType
*MPT
) const {
189 const TargetInfo
&Target
= Context
.getTargetInfo();
190 assert(Target
.getTriple().getArch() == llvm::Triple::x86
||
191 Target
.getTriple().getArch() == llvm::Triple::x86_64
);
193 std::tie(Ptrs
, Ints
) = getMSMemberPointerSlots(MPT
);
194 // The nominal struct is laid out with pointers followed by ints and aligned
195 // to a pointer width if any are present and an int width otherwise.
196 unsigned PtrSize
= Target
.getPointerWidth(0);
197 unsigned IntSize
= Target
.getIntWidth();
198 uint64_t Width
= Ptrs
* PtrSize
+ Ints
* IntSize
;
201 // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
202 // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
204 if (Ptrs
+ Ints
> 1 && Target
.getTriple().getArch() == llvm::Triple::x86
)
207 Align
= Target
.getPointerAlign(0);
209 Align
= Target
.getIntAlign();
211 if (Target
.getTriple().getArch() == llvm::Triple::x86_64
)
212 Width
= llvm::RoundUpToAlignment(Width
, Align
);
213 return std::make_pair(Width
, Align
);
216 CXXABI
*clang::CreateMicrosoftCXXABI(ASTContext
&Ctx
) {
217 return new MicrosoftCXXABI(Ctx
);