1//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides C++ AST support targeting the Microsoft Visual C++
11// ABI.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CXXABI.h"
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"
23
24using namespace clang;
25
26namespace {
27
28/// \brief Numbers things which need to correspond across multiple TUs.
29/// Typically these are things like static locals, lambdas, or blocks.
30class MicrosoftNumberingContext : public MangleNumberingContext {
31  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
32  unsigned LambdaManglingNumber;
33  unsigned StaticLocalNumber;
34
35public:
36  MicrosoftNumberingContext()
37      : MangleNumberingContext(), LambdaManglingNumber(0),
38        StaticLocalNumber(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    return ++StaticLocalNumber;
51  }
52
53  unsigned getManglingNumber(const VarDecl *VD,
54                             unsigned MSLocalManglingNumber) override {
55    return MSLocalManglingNumber;
56  }
57
58  unsigned getManglingNumber(const TagDecl *TD,
59                             unsigned MSLocalManglingNumber) override {
60    return MSLocalManglingNumber;
61  }
62};
63
64class MicrosoftCXXABI : public CXXABI {
65  ASTContext &Context;
66  llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
67  llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
68      CtorToDefaultArgExpr;
69
70public:
71  MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
72
73  std::pair<uint64_t, unsigned>
74  getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override;
75
76  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
77    if (!isVariadic &&
78        Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
79      return CC_X86ThisCall;
80    return CC_C;
81  }
82
83  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
84    // FIXME: Audit the corners
85    if (!RD->isDynamicClass())
86      return false;
87
88    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
89
90    // In the Microsoft ABI, classes can have one or two vtable pointers.
91    CharUnits PointerSize =
92        Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
93    return Layout.getNonVirtualSize() == PointerSize ||
94      Layout.getNonVirtualSize() == PointerSize * 2;
95  }
96
97  void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
98                                       unsigned ParmIdx, Expr *DAE) override {
99    CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
100  }
101
102  Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
103                                        unsigned ParmIdx) override {
104    return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
105  }
106
107  const CXXConstructorDecl *
108  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
109    return RecordToCopyCtor[RD];
110  }
111
112  void
113  addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
114                                       CXXConstructorDecl *CD) override {
115    assert(CD != nullptr);
116    assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
117    RecordToCopyCtor[RD] = CD;
118  }
119
120  MangleNumberingContext *createMangleNumberingContext() const override {
121    return new MicrosoftNumberingContext();
122  }
123};
124}
125
126// getNumBases() seems to only give us the number of direct bases, and not the
127// total.  This function tells us if we inherit from anybody that uses MI, or if
128// we have a non-primary base class, which uses the multiple inheritance model.
129static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
130  while (RD->getNumBases() > 0) {
131    if (RD->getNumBases() > 1)
132      return true;
133    assert(RD->getNumBases() == 1);
134    const CXXRecordDecl *Base =
135        RD->bases_begin()->getType()->getAsCXXRecordDecl();
136    if (RD->isPolymorphic() && !Base->isPolymorphic())
137      return true;
138    RD = Base;
139  }
140  return false;
141}
142
143MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const {
144  if (!hasDefinition() || isParsingBaseSpecifiers())
145    return MSInheritanceAttr::Keyword_unspecified_inheritance;
146  if (getNumVBases() > 0)
147    return MSInheritanceAttr::Keyword_virtual_inheritance;
148  if (usesMultipleInheritanceModel(this))
149    return MSInheritanceAttr::Keyword_multiple_inheritance;
150  return MSInheritanceAttr::Keyword_single_inheritance;
151}
152
153MSInheritanceAttr::Spelling
154CXXRecordDecl::getMSInheritanceModel() const {
155  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
156  assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
157  return IA->getSemanticSpelling();
158}
159
160MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const {
161  if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
162    return VDA->getVtorDispMode();
163  return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode);
164}
165
166// Returns the number of pointer and integer slots used to represent a member
167// pointer in the MS C++ ABI.
168//
169// Member function pointers have the following general form;  however, fields
170// are dropped as permitted (under the MSVC interpretation) by the inheritance
171// model of the actual class.
172//
173//   struct {
174//     // A pointer to the member function to call.  If the member function is
175//     // virtual, this will be a thunk that forwards to the appropriate vftable
176//     // slot.
177//     void *FunctionPointerOrVirtualThunk;
178//
179//     // An offset to add to the address of the vbtable pointer after (possibly)
180//     // selecting the virtual base but before resolving and calling the function.
181//     // Only needed if the class has any virtual bases or bases at a non-zero
182//     // offset.
183//     int NonVirtualBaseAdjustment;
184//
185//     // The offset of the vb-table pointer within the object.  Only needed for
186//     // incomplete types.
187//     int VBPtrOffset;
188//
189//     // An offset within the vb-table that selects the virtual base containing
190//     // the member.  Loading from this offset produces a new offset that is
191//     // added to the address of the vb-table pointer to produce the base.
192//     int VirtualBaseAdjustmentOffset;
193//   };
194static std::pair<unsigned, unsigned>
195getMSMemberPointerSlots(const MemberPointerType *MPT) {
196  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
197  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
198  unsigned Ptrs = 0;
199  unsigned Ints = 0;
200  if (MPT->isMemberFunctionPointer())
201    Ptrs = 1;
202  else
203    Ints = 1;
204  if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(),
205                                          Inheritance))
206    Ints++;
207  if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
208    Ints++;
209  if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
210    Ints++;
211  return std::make_pair(Ptrs, Ints);
212}
213
214std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
215    const MemberPointerType *MPT) const {
216  const TargetInfo &Target = Context.getTargetInfo();
217  assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
218         Target.getTriple().getArch() == llvm::Triple::x86_64);
219  unsigned Ptrs, Ints;
220  std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
221  // The nominal struct is laid out with pointers followed by ints and aligned
222  // to a pointer width if any are present and an int width otherwise.
223  unsigned PtrSize = Target.getPointerWidth(0);
224  unsigned IntSize = Target.getIntWidth();
225  uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
226  unsigned Align;
227
228  // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
229  // 8 bytes.  However, __alignof usually returns 4 for data memptrs and 8 for
230  // function memptrs.
231  if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86)
232    Align = 8 * 8;
233  else if (Ptrs)
234    Align = Target.getPointerAlign(0);
235  else
236    Align = Target.getIntAlign();
237
238  if (Target.getTriple().getArch() == llvm::Triple::x86_64)
239    Width = llvm::RoundUpToAlignment(Width, Align);
240  return std::make_pair(Width, Align);
241}
242
243CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
244  return new MicrosoftCXXABI(Ctx);
245}
246
247