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 
24 using namespace clang;
25 
26 namespace {
27 
28 /// \brief Numbers things which need to correspond across multiple TUs.
29 /// Typically these are things like static locals, lambdas, or blocks.
30 class MicrosoftNumberingContext : public MangleNumberingContext {
31   llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
32   unsigned LambdaManglingNumber;
33   unsigned StaticLocalNumber;
34 
35 public:
MicrosoftNumberingContext()36   MicrosoftNumberingContext()
37       : MangleNumberingContext(), LambdaManglingNumber(0),
38         StaticLocalNumber(0) {}
39 
getManglingNumber(const CXXMethodDecl * CallOperator)40   unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
41     return ++LambdaManglingNumber;
42   }
43 
getManglingNumber(const BlockDecl * BD)44   unsigned getManglingNumber(const BlockDecl *BD) override {
45     const Type *Ty = nullptr;
46     return ++ManglingNumbers[Ty];
47   }
48 
getStaticLocalNumber(const VarDecl * VD)49   unsigned getStaticLocalNumber(const VarDecl *VD) override {
50     return ++StaticLocalNumber;
51   }
52 
getManglingNumber(const VarDecl * VD,unsigned MSLocalManglingNumber)53   unsigned getManglingNumber(const VarDecl *VD,
54                              unsigned MSLocalManglingNumber) override {
55     return MSLocalManglingNumber;
56   }
57 
getManglingNumber(const TagDecl * TD,unsigned MSLocalManglingNumber)58   unsigned getManglingNumber(const TagDecl *TD,
59                              unsigned MSLocalManglingNumber) override {
60     return MSLocalManglingNumber;
61   }
62 };
63 
64 class MicrosoftCXXABI : public CXXABI {
65   ASTContext &Context;
66   llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
67   llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
68       CtorToDefaultArgExpr;
69 
70 public:
MicrosoftCXXABI(ASTContext & Ctx)71   MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
72 
73   std::pair<uint64_t, unsigned>
74   getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override;
75 
getDefaultMethodCallConv(bool isVariadic) const76   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 
isNearlyEmpty(const CXXRecordDecl * RD) const83   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 
addDefaultArgExprForConstructor(const CXXConstructorDecl * CD,unsigned ParmIdx,Expr * DAE)97   void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
98                                        unsigned ParmIdx, Expr *DAE) override {
99     CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
100   }
101 
getDefaultArgExprForConstructor(const CXXConstructorDecl * CD,unsigned ParmIdx)102   Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
103                                         unsigned ParmIdx) override {
104     return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
105   }
106 
107   const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl * RD)108   getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
109     return RecordToCopyCtor[RD];
110   }
111 
112   void
addCopyConstructorForExceptionObject(CXXRecordDecl * RD,CXXConstructorDecl * CD)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 
createMangleNumberingContext() const120   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.
usesMultipleInheritanceModel(const CXXRecordDecl * RD)129 static 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 
calculateInheritanceModel() const143 MSInheritanceAttr::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 
153 MSInheritanceAttr::Spelling
getMSInheritanceModel() const154 CXXRecordDecl::getMSInheritanceModel() const {
155   MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
156   assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
157   return IA->getSemanticSpelling();
158 }
159 
getMSVtorDispMode() const160 MSVtorDispAttr::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 //   };
194 static std::pair<unsigned, unsigned>
getMSMemberPointerSlots(const MemberPointerType * MPT)195 getMSMemberPointerSlots(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 
getMemberPointerWidthAndAlign(const MemberPointerType * MPT) const214 std::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 
CreateMicrosoftCXXABI(ASTContext & Ctx)243 CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
244   return new MicrosoftCXXABI(Ctx);
245 }
246 
247