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"
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"
24
25using namespace clang;
26
27namespace {
28
29/// Numbers things which need to correspond across multiple TUs.
30/// Typically these are things like static locals, lambdas, or blocks.
31class MicrosoftNumberingContext : public MangleNumberingContext {
32  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
33  unsigned LambdaManglingNumber = 0;
34  unsigned StaticLocalNumber = 0;
35  unsigned StaticThreadlocalNumber = 0;
36
37public:
38  MicrosoftNumberingContext() = default;
39
40  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
41    return ++LambdaManglingNumber;
42  }
43
44  unsigned getManglingNumber(const BlockDecl *BD) override {
45    const Type *Ty = nullptr;
46    return ++ManglingNumbers[Ty];
47  }
48
49  unsigned getStaticLocalNumber(const VarDecl *VD) override {
50    if (VD->getTLSKind())
51      return ++StaticThreadlocalNumber;
52    return ++StaticLocalNumber;
53  }
54
55  unsigned getManglingNumber(const VarDecl *VD,
56                             unsigned MSLocalManglingNumber) override {
57    return MSLocalManglingNumber;
58  }
59
60  unsigned getManglingNumber(const TagDecl *TD,
61                             unsigned MSLocalManglingNumber) override {
62    return MSLocalManglingNumber;
63  }
64};
65
66class MSHIPNumberingContext : public MicrosoftNumberingContext {
67  std::unique_ptr<MangleNumberingContext> DeviceCtx;
68
69public:
70  using MicrosoftNumberingContext::getManglingNumber;
71  MSHIPNumberingContext(MangleContext *DeviceMangler) {
72    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
73  }
74
75  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
76    return DeviceCtx->getManglingNumber(CallOperator);
77  }
78
79  unsigned getManglingNumber(const TagDecl *TD,
80                             unsigned MSLocalManglingNumber) override {
81    unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber);
82    unsigned HostN =
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);
89    }
90    return (DeviceN << 16) | HostN;
91  }
92};
93
94class MSSYCLNumberingContext : public MicrosoftNumberingContext {
95  std::unique_ptr<MangleNumberingContext> DeviceCtx;
96
97public:
98  MSSYCLNumberingContext(MangleContext *DeviceMangler) {
99    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
100  }
101
102  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
103    return DeviceCtx->getManglingNumber(CallOperator);
104  }
105};
106
107class MicrosoftCXXABI : public CXXABI {
108  ASTContext &Context;
109  llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
110
111  llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
112      UnnamedTagDeclToDeclaratorDecl;
113  llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
114      UnnamedTagDeclToTypedefNameDecl;
115
116  // MangleContext for device numbering context, which is based on Itanium C++
117  // ABI.
118  std::unique_ptr<MangleContext> DeviceMangler;
119
120public:
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.");
126      DeviceMangler.reset(
127          Context.createMangleContext(Context.getAuxTargetInfo()));
128    }
129    else if (Context.getLangOpts().isSYCL()) {
130      DeviceMangler.reset(
131          ItaniumMangleContext::create(Context, Context.getDiagnostics()));
132    }
133  }
134
135  MemberPointerInfo
136  getMemberPointerInfo(const MemberPointerType *MPT) const override;
137
138  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
139    if (!isVariadic &&
140        Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
141      return CC_X86ThisCall;
142    return Context.getTargetInfo().getDefaultCallingConv();
143  }
144
145  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
146    llvm_unreachable("unapplicable to the MS ABI");
147  }
148
149  const CXXConstructorDecl *
150  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
151    return RecordToCopyCtor[RD];
152  }
153
154  void
155  addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
156                                       CXXConstructorDecl *CD) override {
157    assert(CD != nullptr);
158    assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
159    RecordToCopyCtor[RD] = CD;
160  }
161
162  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
163                                       TypedefNameDecl *DD) override {
164    TD = TD->getCanonicalDecl();
165    DD = DD->getCanonicalDecl();
166    TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
167    if (!I)
168      I = DD;
169  }
170
171  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
172    return UnnamedTagDeclToTypedefNameDecl.lookup(
173        const_cast<TagDecl *>(TD->getCanonicalDecl()));
174  }
175
176  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
177                                      DeclaratorDecl *DD) override {
178    TD = TD->getCanonicalDecl();
179    DD = cast<DeclaratorDecl>(DD->getCanonicalDecl());
180    DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
181    if (!I)
182      I = DD;
183  }
184
185  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
186    return UnnamedTagDeclToDeclaratorDecl.lookup(
187        const_cast<TagDecl *>(TD->getCanonicalDecl()));
188  }
189
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());
198    }
199
200    return std::make_unique<MicrosoftNumberingContext>();
201  }
202};
203}
204
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.
208static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
209  while (RD->getNumBases() > 0) {
210    if (RD->getNumBases() > 1)
211      return true;
212    assert(RD->getNumBases() == 1);
213    const CXXRecordDecl *Base =
214        RD->bases_begin()->getType()->getAsCXXRecordDecl();
215    if (RD->isPolymorphic() && !Base->isPolymorphic())
216      return true;
217    RD = Base;
218  }
219  return false;
220}
221
222MSInheritanceModel 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;
230}
231
232MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
233  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
234  assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
235  return IA->getInheritanceModel();
236}
237
238bool CXXRecordDecl::nullFieldOffsetIsZero() const {
239  return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false,
240                                          getMSInheritanceModel()) ||
241         (hasDefinition() && isPolymorphic());
242}
243
244MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const {
245  if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
246    return VDA->getVtorDispMode();
247  return getASTContext().getLangOpts().getVtorDispMode();
248}
249
250// Returns the number of pointer and integer slots used to represent a member
251// pointer in the MS C++ ABI.
252//
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.
256//
257//   struct {
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
260//     // slot.
261//     void *FunctionPointerOrVirtualThunk;
262//
263//     // An offset to add to the address of the vbtable pointer after
264//     // (possibly) selecting the virtual base but before resolving and calling
265//     // the function.
266//     // Only needed if the class has any virtual bases or bases at a non-zero
267//     // offset.
268//     int NonVirtualBaseAdjustment;
269//
270//     // The offset of the vb-table pointer within the object.  Only needed for
271//     // incomplete types.
272//     int VBPtrOffset;
273//
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;
278//   };
279static std::pair<unsigned, unsigned>
280getMSMemberPointerSlots(const MemberPointerType *MPT) {
281  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
282  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
283  unsigned Ptrs = 0;
284  unsigned Ints = 0;
285  if (MPT->isMemberFunctionPointer())
286    Ptrs = 1;
287  else
288    Ints = 1;
289  if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(),
290                                          Inheritance))
291    Ints++;
292  if (inheritanceModelHasVBPtrOffsetField(Inheritance))
293    Ints++;
294  if (inheritanceModelHasVBTableOffsetField(Inheritance))
295    Ints++;
296  return std::make_pair(Ptrs, Ints);
297}
298
299CXXABI::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();
306
307  unsigned Ptrs, Ints;
308  std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
309  MemberPointerInfo MPI;
310  MPI.HasPadding = false;
311  MPI.Width = Ptrs * PtrSize + Ints * IntSize;
312
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
315  // function memptrs.
316  if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
317    MPI.Align = 64;
318  else if (Ptrs)
319    MPI.Align = Target.getPointerAlign(LangAS::Default);
320  else
321    MPI.Align = Target.getIntAlign();
322
323  if (Target.getTriple().isArch64Bit()) {
324    MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
325    MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
326  }
327  return MPI;
328}
329
330CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
331  return new MicrosoftCXXABI(Ctx);
332}
333