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