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