1 //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This provides C++ AST support targeting the Microsoft Visual C++
12 //===----------------------------------------------------------------------===//
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Attr.h"
17 #include "clang/AST/CXXInheritance.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/Mangle.h"
20 #include "clang/AST/MangleNumberingContext.h"
21 #include "clang/AST/RecordLayout.h"
22 #include "clang/AST/Type.h"
23 #include "clang/Basic/TargetInfo.h"
25 using namespace clang
;
29 /// Numbers things which need to correspond across multiple TUs.
30 /// Typically these are things like static locals, lambdas, or blocks.
31 class MicrosoftNumberingContext
: public MangleNumberingContext
{
32 llvm::DenseMap
<const Type
*, unsigned> ManglingNumbers
;
33 unsigned LambdaManglingNumber
= 0;
34 unsigned StaticLocalNumber
= 0;
35 unsigned StaticThreadlocalNumber
= 0;
38 MicrosoftNumberingContext() = default;
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
{
51 return ++StaticThreadlocalNumber
;
52 return ++StaticLocalNumber
;
55 unsigned getManglingNumber(const VarDecl
*VD
,
56 unsigned MSLocalManglingNumber
) override
{
57 return MSLocalManglingNumber
;
60 unsigned getManglingNumber(const TagDecl
*TD
,
61 unsigned MSLocalManglingNumber
) override
{
62 return MSLocalManglingNumber
;
66 class MSHIPNumberingContext
: public MicrosoftNumberingContext
{
67 std::unique_ptr
<MangleNumberingContext
> DeviceCtx
;
70 using MicrosoftNumberingContext::getManglingNumber
;
71 MSHIPNumberingContext(MangleContext
*DeviceMangler
) {
72 DeviceCtx
= createItaniumNumberingContext(DeviceMangler
);
75 unsigned getDeviceManglingNumber(const CXXMethodDecl
*CallOperator
) override
{
76 return DeviceCtx
->getManglingNumber(CallOperator
);
79 unsigned getManglingNumber(const TagDecl
*TD
,
80 unsigned MSLocalManglingNumber
) override
{
81 unsigned DeviceN
= DeviceCtx
->getManglingNumber(TD
, MSLocalManglingNumber
);
83 MicrosoftNumberingContext::getManglingNumber(TD
, MSLocalManglingNumber
);
84 if (DeviceN
> 0xFFFF || HostN
> 0xFFFF) {
85 DiagnosticsEngine
&Diags
= TD
->getASTContext().getDiagnostics();
86 unsigned DiagID
= Diags
.getCustomDiagID(
87 DiagnosticsEngine::Error
, "Mangling number exceeds limit (65535)");
88 Diags
.Report(TD
->getLocation(), DiagID
);
90 return (DeviceN
<< 16) | HostN
;
94 class MSSYCLNumberingContext
: public MicrosoftNumberingContext
{
95 std::unique_ptr
<MangleNumberingContext
> DeviceCtx
;
98 MSSYCLNumberingContext(MangleContext
*DeviceMangler
) {
99 DeviceCtx
= createItaniumNumberingContext(DeviceMangler
);
102 unsigned getDeviceManglingNumber(const CXXMethodDecl
*CallOperator
) override
{
103 return DeviceCtx
->getManglingNumber(CallOperator
);
107 class MicrosoftCXXABI
: public CXXABI
{
109 llvm::SmallDenseMap
<CXXRecordDecl
*, CXXConstructorDecl
*> RecordToCopyCtor
;
111 llvm::SmallDenseMap
<TagDecl
*, DeclaratorDecl
*>
112 UnnamedTagDeclToDeclaratorDecl
;
113 llvm::SmallDenseMap
<TagDecl
*, TypedefNameDecl
*>
114 UnnamedTagDeclToTypedefNameDecl
;
116 // MangleContext for device numbering context, which is based on Itanium C++
118 std::unique_ptr
<MangleContext
> DeviceMangler
;
121 MicrosoftCXXABI(ASTContext
&Ctx
) : Context(Ctx
) {
122 if (Context
.getLangOpts().CUDA
&& Context
.getAuxTargetInfo()) {
123 assert(Context
.getTargetInfo().getCXXABI().isMicrosoft() &&
124 Context
.getAuxTargetInfo()->getCXXABI().isItaniumFamily() &&
125 "Unexpected combination of C++ ABIs.");
127 Context
.createMangleContext(Context
.getAuxTargetInfo()));
129 else if (Context
.getLangOpts().isSYCL()) {
131 ItaniumMangleContext::create(Context
, Context
.getDiagnostics()));
136 getMemberPointerInfo(const MemberPointerType
*MPT
) const override
;
138 CallingConv
getDefaultMethodCallConv(bool isVariadic
) const override
{
140 Context
.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
)
141 return CC_X86ThisCall
;
142 return Context
.getTargetInfo().getDefaultCallingConv();
145 bool isNearlyEmpty(const CXXRecordDecl
*RD
) const override
{
146 llvm_unreachable("unapplicable to the MS ABI");
149 const CXXConstructorDecl
*
150 getCopyConstructorForExceptionObject(CXXRecordDecl
*RD
) override
{
151 return RecordToCopyCtor
[RD
];
155 addCopyConstructorForExceptionObject(CXXRecordDecl
*RD
,
156 CXXConstructorDecl
*CD
) override
{
157 assert(CD
!= nullptr);
158 assert(RecordToCopyCtor
[RD
] == nullptr || RecordToCopyCtor
[RD
] == CD
);
159 RecordToCopyCtor
[RD
] = CD
;
162 void addTypedefNameForUnnamedTagDecl(TagDecl
*TD
,
163 TypedefNameDecl
*DD
) override
{
164 TD
= TD
->getCanonicalDecl();
165 DD
= DD
->getCanonicalDecl();
166 TypedefNameDecl
*&I
= UnnamedTagDeclToTypedefNameDecl
[TD
];
171 TypedefNameDecl
*getTypedefNameForUnnamedTagDecl(const TagDecl
*TD
) override
{
172 return UnnamedTagDeclToTypedefNameDecl
.lookup(
173 const_cast<TagDecl
*>(TD
->getCanonicalDecl()));
176 void addDeclaratorForUnnamedTagDecl(TagDecl
*TD
,
177 DeclaratorDecl
*DD
) override
{
178 TD
= TD
->getCanonicalDecl();
179 DD
= cast
<DeclaratorDecl
>(DD
->getCanonicalDecl());
180 DeclaratorDecl
*&I
= UnnamedTagDeclToDeclaratorDecl
[TD
];
185 DeclaratorDecl
*getDeclaratorForUnnamedTagDecl(const TagDecl
*TD
) override
{
186 return UnnamedTagDeclToDeclaratorDecl
.lookup(
187 const_cast<TagDecl
*>(TD
->getCanonicalDecl()));
190 std::unique_ptr
<MangleNumberingContext
>
191 createMangleNumberingContext() const override
{
192 if (Context
.getLangOpts().CUDA
&& Context
.getAuxTargetInfo()) {
193 assert(DeviceMangler
&& "Missing device mangler");
194 return std::make_unique
<MSHIPNumberingContext
>(DeviceMangler
.get());
195 } else if (Context
.getLangOpts().isSYCL()) {
196 assert(DeviceMangler
&& "Missing device mangler");
197 return std::make_unique
<MSSYCLNumberingContext
>(DeviceMangler
.get());
200 return std::make_unique
<MicrosoftNumberingContext
>();
205 // getNumBases() seems to only give us the number of direct bases, and not the
206 // total. This function tells us if we inherit from anybody that uses MI, or if
207 // we have a non-primary base class, which uses the multiple inheritance model.
208 static bool usesMultipleInheritanceModel(const CXXRecordDecl
*RD
) {
209 while (RD
->getNumBases() > 0) {
210 if (RD
->getNumBases() > 1)
212 assert(RD
->getNumBases() == 1);
213 const CXXRecordDecl
*Base
=
214 RD
->bases_begin()->getType()->getAsCXXRecordDecl();
215 if (RD
->isPolymorphic() && !Base
->isPolymorphic())
222 MSInheritanceModel
CXXRecordDecl::calculateInheritanceModel() const {
223 if (!hasDefinition() || isParsingBaseSpecifiers())
224 return MSInheritanceModel::Unspecified
;
225 if (getNumVBases() > 0)
226 return MSInheritanceModel::Virtual
;
227 if (usesMultipleInheritanceModel(this))
228 return MSInheritanceModel::Multiple
;
229 return MSInheritanceModel::Single
;
232 MSInheritanceModel
CXXRecordDecl::getMSInheritanceModel() const {
233 MSInheritanceAttr
*IA
= getAttr
<MSInheritanceAttr
>();
234 assert(IA
&& "Expected MSInheritanceAttr on the CXXRecordDecl!");
235 return IA
->getInheritanceModel();
238 bool CXXRecordDecl::nullFieldOffsetIsZero() const {
239 return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false,
240 getMSInheritanceModel()) ||
241 (hasDefinition() && isPolymorphic());
244 MSVtorDispMode
CXXRecordDecl::getMSVtorDispMode() const {
245 if (MSVtorDispAttr
*VDA
= getAttr
<MSVtorDispAttr
>())
246 return VDA
->getVtorDispMode();
247 return getASTContext().getLangOpts().getVtorDispMode();
250 // Returns the number of pointer and integer slots used to represent a member
251 // pointer in the MS C++ ABI.
253 // Member function pointers have the following general form; however, fields
254 // are dropped as permitted (under the MSVC interpretation) by the inheritance
255 // model of the actual class.
258 // // A pointer to the member function to call. If the member function is
259 // // virtual, this will be a thunk that forwards to the appropriate vftable
261 // void *FunctionPointerOrVirtualThunk;
263 // // An offset to add to the address of the vbtable pointer after
264 // // (possibly) selecting the virtual base but before resolving and calling
266 // // Only needed if the class has any virtual bases or bases at a non-zero
268 // int NonVirtualBaseAdjustment;
270 // // The offset of the vb-table pointer within the object. Only needed for
271 // // incomplete types.
274 // // An offset within the vb-table that selects the virtual base containing
275 // // the member. Loading from this offset produces a new offset that is
276 // // added to the address of the vb-table pointer to produce the base.
277 // int VirtualBaseAdjustmentOffset;
279 static std::pair
<unsigned, unsigned>
280 getMSMemberPointerSlots(const MemberPointerType
*MPT
) {
281 const CXXRecordDecl
*RD
= MPT
->getMostRecentCXXRecordDecl();
282 MSInheritanceModel Inheritance
= RD
->getMSInheritanceModel();
285 if (MPT
->isMemberFunctionPointer())
289 if (inheritanceModelHasNVOffsetField(MPT
->isMemberFunctionPointer(),
292 if (inheritanceModelHasVBPtrOffsetField(Inheritance
))
294 if (inheritanceModelHasVBTableOffsetField(Inheritance
))
296 return std::make_pair(Ptrs
, Ints
);
299 CXXABI::MemberPointerInfo
MicrosoftCXXABI::getMemberPointerInfo(
300 const MemberPointerType
*MPT
) const {
301 // The nominal struct is laid out with pointers followed by ints and aligned
302 // to a pointer width if any are present and an int width otherwise.
303 const TargetInfo
&Target
= Context
.getTargetInfo();
304 unsigned PtrSize
= Target
.getPointerWidth(LangAS::Default
);
305 unsigned IntSize
= Target
.getIntWidth();
308 std::tie(Ptrs
, Ints
) = getMSMemberPointerSlots(MPT
);
309 MemberPointerInfo MPI
;
310 MPI
.HasPadding
= false;
311 MPI
.Width
= Ptrs
* PtrSize
+ Ints
* IntSize
;
313 // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
314 // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
316 if (Ptrs
+ Ints
> 1 && Target
.getTriple().isArch32Bit())
319 MPI
.Align
= Target
.getPointerAlign(LangAS::Default
);
321 MPI
.Align
= Target
.getIntAlign();
323 if (Target
.getTriple().isArch64Bit()) {
324 MPI
.Width
= llvm::alignTo(MPI
.Width
, MPI
.Align
);
325 MPI
.HasPadding
= MPI
.Width
!= (Ptrs
* PtrSize
+ Ints
* IntSize
);
330 CXXABI
*clang::CreateMicrosoftCXXABI(ASTContext
&Ctx
) {
331 return new MicrosoftCXXABI(Ctx
);