Clang Project

clang_source_code/lib/AST/MicrosoftCXXABI.cpp
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/DeclCXX.h"
18#include "clang/AST/MangleNumberingContext.h"
19#include "clang/AST/RecordLayout.h"
20#include "clang/AST/Type.h"
21#include "clang/Basic/TargetInfo.h"
22
23using namespace clang;
24
25namespace {
26
27/// Numbers things which need to correspond across multiple TUs.
28/// Typically these are things like static locals, lambdas, or blocks.
29class MicrosoftNumberingContext : public MangleNumberingContext {
30  llvm::DenseMap<const Type *, unsignedManglingNumbers;
31  unsigned LambdaManglingNumber;
32  unsigned StaticLocalNumber;
33  unsigned StaticThreadlocalNumber;
34
35public:
36  MicrosoftNumberingContext()
37      : MangleNumberingContext(), LambdaManglingNumber(0),
38        StaticLocalNumber(0), StaticThreadlocalNumber(0) {}
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 MicrosoftCXXABI : public CXXABI {
67  ASTContext &Context;
68  llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
69
70  llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
71      UnnamedTagDeclToDeclaratorDecl;
72  llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
73      UnnamedTagDeclToTypedefNameDecl;
74
75public:
76  MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
77
78  MemberPointerInfo
79  getMemberPointerInfo(const MemberPointerType *MPTconst override;
80
81  CallingConv getDefaultMethodCallConv(bool isVariadicconst override {
82    if (!isVariadic &&
83        Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
84      return CC_X86ThisCall;
85    return CC_C;
86  }
87
88  bool isNearlyEmpty(const CXXRecordDecl *RDconst override {
89    llvm_unreachable("unapplicable to the MS ABI");
90  }
91
92  const CXXConstructorDecl *
93  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
94    return RecordToCopyCtor[RD];
95  }
96
97  void
98  addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
99                                       CXXConstructorDecl *CD) override {
100    assert(CD != nullptr);
101    assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
102    RecordToCopyCtor[RD] = CD;
103  }
104
105  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
106                                       TypedefNameDecl *DD) override {
107    TD = TD->getCanonicalDecl();
108    DD = DD->getCanonicalDecl();
109    TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
110    if (!I)
111      I = DD;
112  }
113
114  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
115    return UnnamedTagDeclToTypedefNameDecl.lookup(
116        const_cast<TagDecl *>(TD->getCanonicalDecl()));
117  }
118
119  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
120                                      DeclaratorDecl *DD) override {
121    TD = TD->getCanonicalDecl();
122    DD = cast<DeclaratorDecl>(DD->getCanonicalDecl());
123    DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
124    if (!I)
125      I = DD;
126  }
127
128  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
129    return UnnamedTagDeclToDeclaratorDecl.lookup(
130        const_cast<TagDecl *>(TD->getCanonicalDecl()));
131  }
132
133  std::unique_ptr<MangleNumberingContext>
134  createMangleNumberingContext() const override {
135    return llvm::make_unique<MicrosoftNumberingContext>();
136  }
137};
138}
139
140// getNumBases() seems to only give us the number of direct bases, and not the
141// total.  This function tells us if we inherit from anybody that uses MI, or if
142// we have a non-primary base class, which uses the multiple inheritance model.
143static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
144  while (RD->getNumBases() > 0) {
145    if (RD->getNumBases() > 1)
146      return true;
147    getNumBases() == 1", "/home/seafit/code_projects/clang_source/clang/lib/AST/MicrosoftCXXABI.cpp", 147, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(RD->getNumBases() == 1);
148    const CXXRecordDecl *Base =
149        RD->bases_begin()->getType()->getAsCXXRecordDecl();
150    if (RD->isPolymorphic() && !Base->isPolymorphic())
151      return true;
152    RD = Base;
153  }
154  return false;
155}
156
157MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const {
158  if (!hasDefinition() || isParsingBaseSpecifiers())
159    return MSInheritanceAttr::Keyword_unspecified_inheritance;
160  if (getNumVBases() > 0)
161    return MSInheritanceAttr::Keyword_virtual_inheritance;
162  if (usesMultipleInheritanceModel(this))
163    return MSInheritanceAttr::Keyword_multiple_inheritance;
164  return MSInheritanceAttr::Keyword_single_inheritance;
165}
166
167MSInheritanceAttr::Spelling
168CXXRecordDecl::getMSInheritanceModel() const {
169  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
170   (0) . __assert_fail ("IA && \"Expected MSInheritanceAttr on the CXXRecordDecl!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/MicrosoftCXXABI.cpp", 170, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
171  return IA->getSemanticSpelling();
172}
173
174MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const {
175  if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
176    return VDA->getVtorDispMode();
177  return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode);
178}
179
180// Returns the number of pointer and integer slots used to represent a member
181// pointer in the MS C++ ABI.
182//
183// Member function pointers have the following general form;  however, fields
184// are dropped as permitted (under the MSVC interpretation) by the inheritance
185// model of the actual class.
186//
187//   struct {
188//     // A pointer to the member function to call.  If the member function is
189//     // virtual, this will be a thunk that forwards to the appropriate vftable
190//     // slot.
191//     void *FunctionPointerOrVirtualThunk;
192//
193//     // An offset to add to the address of the vbtable pointer after
194//     // (possibly) selecting the virtual base but before resolving and calling
195//     // the function.
196//     // Only needed if the class has any virtual bases or bases at a non-zero
197//     // offset.
198//     int NonVirtualBaseAdjustment;
199//
200//     // The offset of the vb-table pointer within the object.  Only needed for
201//     // incomplete types.
202//     int VBPtrOffset;
203//
204//     // An offset within the vb-table that selects the virtual base containing
205//     // the member.  Loading from this offset produces a new offset that is
206//     // added to the address of the vb-table pointer to produce the base.
207//     int VirtualBaseAdjustmentOffset;
208//   };
209static std::pair<unsignedunsigned>
210getMSMemberPointerSlots(const MemberPointerType *MPT) {
211  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
212  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
213  unsigned Ptrs = 0;
214  unsigned Ints = 0;
215  if (MPT->isMemberFunctionPointer())
216    Ptrs = 1;
217  else
218    Ints = 1;
219  if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(),
220                                          Inheritance))
221    Ints++;
222  if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
223    Ints++;
224  if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
225    Ints++;
226  return std::make_pair(PtrsInts);
227}
228
229CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
230    const MemberPointerType *MPTconst {
231  // The nominal struct is laid out with pointers followed by ints and aligned
232  // to a pointer width if any are present and an int width otherwise.
233  const TargetInfo &Target = Context.getTargetInfo();
234  unsigned PtrSize = Target.getPointerWidth(0);
235  unsigned IntSize = Target.getIntWidth();
236
237  unsigned PtrsInts;
238  std::tie(PtrsInts) = getMSMemberPointerSlots(MPT);
239  MemberPointerInfo MPI;
240  MPI.HasPadding = false;
241  MPI.Width = Ptrs * PtrSize + Ints * IntSize;
242
243  // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
244  // 8 bytes.  However, __alignof usually returns 4 for data memptrs and 8 for
245  // function memptrs.
246  if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
247    MPI.Align = 64;
248  else if (Ptrs)
249    MPI.Align = Target.getPointerAlign(0);
250  else
251    MPI.Align = Target.getIntAlign();
252
253  if (Target.getTriple().isArch64Bit()) {
254    MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
255    MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
256  }
257  return MPI;
258}
259
260CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
261  return new MicrosoftCXXABI(Ctx);
262}
263
264
clang::CXXRecordDecl::calculateInheritanceModel
clang::CXXRecordDecl::getMSInheritanceModel
clang::CXXRecordDecl::getMSVtorDispMode