clang 23.0.0git
MicrosoftCXXABI.cpp
Go to the documentation of this file.
1//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This provides C++ AST support targeting the Microsoft Visual C++
10// ABI.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CXXABI.h"
16#include "clang/AST/Attr.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Mangle.h"
22#include "clang/AST/Type.h"
25
26using namespace clang;
27
28namespace {
29
30/// Numbers things which need to correspond across multiple TUs.
31/// Typically these are things like static locals, lambdas, or blocks.
32class MicrosoftNumberingContext : public MangleNumberingContext {
33 llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
34 unsigned LambdaManglingNumber = 0;
35 unsigned StaticLocalNumber = 0;
36 unsigned StaticThreadlocalNumber = 0;
37
38public:
39 MicrosoftNumberingContext() = default;
40
41 unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
42 return ++LambdaManglingNumber;
43 }
44
45 unsigned getManglingNumber(const BlockDecl *BD) override {
46 const Type *Ty = nullptr;
47 return ++ManglingNumbers[Ty];
48 }
49
50 unsigned getStaticLocalNumber(const VarDecl *VD) override {
51 if (VD->getTLSKind())
52 return ++StaticThreadlocalNumber;
53 return ++StaticLocalNumber;
54 }
55
56 unsigned getManglingNumber(const VarDecl *VD,
57 unsigned MSLocalManglingNumber) override {
58 return MSLocalManglingNumber;
59 }
60
61 unsigned getManglingNumber(const TagDecl *TD,
62 unsigned MSLocalManglingNumber) override {
63 return MSLocalManglingNumber;
64 }
65};
66
67class MSHIPNumberingContext : public MicrosoftNumberingContext {
68 std::unique_ptr<MangleNumberingContext> DeviceCtx;
69
70public:
71 using MicrosoftNumberingContext::getManglingNumber;
72 MSHIPNumberingContext(MangleContext *DeviceMangler) {
73 DeviceCtx = createItaniumNumberingContext(DeviceMangler);
74 }
75
76 unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
77 return DeviceCtx->getManglingNumber(CallOperator);
78 }
79
80 unsigned getManglingNumber(const TagDecl *TD,
81 unsigned MSLocalManglingNumber) override {
82 unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber);
83 unsigned HostN =
84 MicrosoftNumberingContext::getManglingNumber(TD, MSLocalManglingNumber);
85 if (DeviceN > 0xFFFF || HostN > 0xFFFF) {
86 DiagnosticsEngine &Diags = TD->getASTContext().getDiagnostics();
87 Diags.Report(TD->getLocation(), diag::err_ms_mangle_number_overflow);
88 }
89 return (DeviceN << 16) | HostN;
90 }
91};
92
93class MSSYCLNumberingContext : public MicrosoftNumberingContext {
94 std::unique_ptr<MangleNumberingContext> DeviceCtx;
95
96public:
97 MSSYCLNumberingContext(MangleContext *DeviceMangler) {
98 DeviceCtx = createItaniumNumberingContext(DeviceMangler);
99 }
100
101 unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
102 return DeviceCtx->getManglingNumber(CallOperator);
103 }
104};
105
106class MicrosoftCXXABI : public CXXABI {
107 ASTContext &Context;
108 llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
109
110 llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
111 UnnamedTagDeclToDeclaratorDecl;
112 llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
113 UnnamedTagDeclToTypedefNameDecl;
114
115 // MangleContext for device numbering context, which is based on Itanium C++
116 // ABI.
117 std::unique_ptr<MangleContext> DeviceMangler;
118
119public:
120 MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) {
121 if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) {
122 assert(Context.getTargetInfo().getCXXABI().isMicrosoft() &&
123 Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() &&
124 "Unexpected combination of C++ ABIs.");
125 DeviceMangler.reset(
126 Context.createMangleContext(Context.getAuxTargetInfo()));
127 }
128 else if (Context.getLangOpts().isSYCL()) {
129 DeviceMangler.reset(
130 ItaniumMangleContext::create(Context, Context.getDiagnostics()));
131 }
132 }
133
134 MemberPointerInfo
135 getMemberPointerInfo(const MemberPointerType *MPT) const override;
136
137 CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
138 if (!isVariadic &&
139 Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
140 return CC_X86ThisCall;
141 return Context.getTargetInfo().getDefaultCallingConv();
142 }
143
144 bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
145 llvm_unreachable("unapplicable to the MS ABI");
146 }
147
148 const CXXConstructorDecl *
149 getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
150 return RecordToCopyCtor[RD];
151 }
152
153 void
154 addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
155 CXXConstructorDecl *CD) override {
156 assert(CD != nullptr);
157 assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
158 RecordToCopyCtor[RD] = CD;
159 }
160
161 void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
162 TypedefNameDecl *DD) override {
163 TD = TD->getCanonicalDecl();
164 DD = DD->getCanonicalDecl();
165 TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
166 if (!I)
167 I = DD;
168 }
169
170 TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
171 return UnnamedTagDeclToTypedefNameDecl.lookup(
172 const_cast<TagDecl *>(TD->getCanonicalDecl()));
173 }
174
175 void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
176 DeclaratorDecl *DD) override {
177 TD = TD->getCanonicalDecl();
179 DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
180 if (!I)
181 I = DD;
182 }
183
184 DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
185 return UnnamedTagDeclToDeclaratorDecl.lookup(
186 const_cast<TagDecl *>(TD->getCanonicalDecl()));
187 }
188
189 std::unique_ptr<MangleNumberingContext>
190 createMangleNumberingContext() const override {
191 if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) {
192 assert(DeviceMangler && "Missing device mangler");
193 return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
194 } else if (Context.getLangOpts().isSYCL()) {
195 assert(DeviceMangler && "Missing device mangler");
196 return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get());
197 }
198
199 return std::make_unique<MicrosoftNumberingContext>();
200 }
201};
202}
203
204// getNumBases() seems to only give us the number of direct bases, and not the
205// total. This function tells us if we inherit from anybody that uses MI, or if
206// we have a non-primary base class, which uses the multiple inheritance model.
208 while (RD->getNumBases() > 0) {
209 if (RD->getNumBases() > 1)
210 return true;
211 assert(RD->getNumBases() == 1);
212 const CXXRecordDecl *Base =
214 if (RD->isPolymorphic() && !Base->isPolymorphic())
215 return true;
216 RD = Base;
217 }
218 return false;
219}
220
230
232 MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
233 assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
234 return IA->getInheritanceModel();
235}
236
238 return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false,
241}
242
244 if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
245 return VDA->getVtorDispMode();
246 return getASTContext().getLangOpts().getVtorDispMode();
247}
248
249// Returns the number of pointer and integer slots used to represent a member
250// pointer in the MS C++ ABI.
251//
252// Member function pointers have the following general form; however, fields
253// are dropped as permitted (under the MSVC interpretation) by the inheritance
254// model of the actual class.
255//
256// struct {
257// // A pointer to the member function to call. If the member function is
258// // virtual, this will be a thunk that forwards to the appropriate vftable
259// // slot.
260// void *FunctionPointerOrVirtualThunk;
261//
262// // An offset to add to the address of the vbtable pointer after
263// // (possibly) selecting the virtual base but before resolving and calling
264// // the function.
265// // Only needed if the class has any virtual bases or bases at a non-zero
266// // offset.
267// int NonVirtualBaseAdjustment;
268//
269// // The offset of the vb-table pointer within the object. Only needed for
270// // incomplete types.
271// int VBPtrOffset;
272//
273// // An offset within the vb-table that selects the virtual base containing
274// // the member. Loading from this offset produces a new offset that is
275// // added to the address of the vb-table pointer to produce the base.
276// int VirtualBaseAdjustmentOffset;
277// };
278static std::pair<unsigned, unsigned>
280 const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
281 MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
282 unsigned Ptrs = 0;
283 unsigned Ints = 0;
284 if (MPT->isMemberFunctionPointer())
285 Ptrs = 1;
286 else
287 Ints = 1;
289 Inheritance))
290 Ints++;
292 Ints++;
294 Ints++;
295 return std::make_pair(Ptrs, Ints);
296}
297
298CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
299 const MemberPointerType *MPT) const {
300 // The nominal struct is laid out with pointers followed by ints and aligned
301 // to a pointer width if any are present and an int width otherwise.
302 const TargetInfo &Target = Context.getTargetInfo();
303 unsigned PtrSize = Target.getPointerWidth(LangAS::Default);
304 unsigned IntSize = Target.getIntWidth();
305
306 unsigned Ptrs, Ints;
307 std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
308 MemberPointerInfo MPI;
309 MPI.HasPadding = false;
310 MPI.Width = Ptrs * PtrSize + Ints * IntSize;
311
312 // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
313 // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
314 // function memptrs.
315 if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
316 MPI.Align = 64;
317 else if (Ptrs)
318 MPI.Align = Target.getPointerAlign(LangAS::Default);
319 else
320 MPI.Align = Target.getIntAlign();
321
322 if (Target.getTriple().isArch64Bit()) {
323 MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
324 MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
325 }
326 return MPI;
327}
328
330 return new MicrosoftCXXABI(Ctx);
331}
Defines the clang::ASTContext interface.
static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD)
static std::pair< unsigned, unsigned > getMSMemberPointerSlots(const MemberPointerType *MPT)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define CXXABI(Name, Str)
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
const LangOptions & getLangOpts() const
Definition ASTContext.h:951
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:916
Implements C++ ABI-specific semantic analysis functions.
Definition CXXABI.h:29
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isParsingBaseSpecifiers() const
Definition DeclCXX.h:592
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
Definition DeclCXX.h:1214
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:602
base_class_iterator bases_begin()
Definition DeclCXX.h:615
MSInheritanceModel getMSInheritanceModel() const
Returns the inheritance model used for this record.
bool nullFieldOffsetIsZero() const
In the Microsoft C++ ABI, use zero for the field offset of a null data member pointer if we can guara...
bool hasDefinition() const
Definition DeclCXX.h:561
MSInheritanceModel calculateInheritanceModel() const
Calculate what the inheritance model would be for this class.
MSVtorDispMode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
T * getAttr() const
Definition DeclBase.h:573
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:546
SourceLocation getLocation() const
Definition DeclBase.h:439
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Keeps track of the mangled names of lambda expressions and block literals within a particular context...
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3661
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5530
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
Definition TypeBase.h:3683
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:4900
Exposes information about the current target.
Definition TargetInfo.h:226
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
TypedefNameDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this typedef-name.
Definition Decl.h:3633
TLSKind getTLSKind() const
Definition Decl.cpp:2180
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
std::unique_ptr< MangleNumberingContext > createItaniumNumberingContext(MangleContext *)
CXXABI * CreateMicrosoftCXXABI(ASTContext &Ctx)
bool inheritanceModelHasNVOffsetField(bool IsMemberFunction, MSInheritanceModel Inheritance)
bool inheritanceModelHasOnlyOneField(bool IsMemberFunction, MSInheritanceModel Inheritance)
bool inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance)
bool inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance)
MSVtorDispMode
In the Microsoft ABI, this controls the placement of virtual displacement members used to implement v...
Definition LangOptions.h:38
@ Type
The name was classified as a type.
Definition Sema.h:564
MSInheritanceModel
Assigned inheritance model for a class in the MS C++ ABI.
Definition Specifiers.h:410
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition Specifiers.h:278
@ CC_X86ThisCall
Definition Specifiers.h:282
U cast(CodeGen::Address addr)
Definition Address.h:327