/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/MicrosoftCXXABI.cpp
Line | Count | Source (jump to first uncovered line) |
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/CXXInheritance.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 | | /// 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 | | unsigned StaticThreadlocalNumber; |
35 | | |
36 | | public: |
37 | | MicrosoftNumberingContext() |
38 | | : MangleNumberingContext(), LambdaManglingNumber(0), |
39 | 2.12k | StaticLocalNumber(0), StaticThreadlocalNumber(0) {} |
40 | | |
41 | 1.61k | unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { |
42 | 1.61k | return ++LambdaManglingNumber; |
43 | 1.61k | } |
44 | | |
45 | 24 | unsigned getManglingNumber(const BlockDecl *BD) override { |
46 | 24 | const Type *Ty = nullptr; |
47 | 24 | return ++ManglingNumbers[Ty]; |
48 | 24 | } |
49 | | |
50 | 111 | unsigned getStaticLocalNumber(const VarDecl *VD) override { |
51 | 111 | if (VD->getTLSKind()) |
52 | 11 | return ++StaticThreadlocalNumber; |
53 | 100 | return ++StaticLocalNumber; |
54 | 100 | } |
55 | | |
56 | | unsigned getManglingNumber(const VarDecl *VD, |
57 | 111 | unsigned MSLocalManglingNumber) override { |
58 | 111 | return MSLocalManglingNumber; |
59 | 111 | } |
60 | | |
61 | | unsigned getManglingNumber(const TagDecl *TD, |
62 | 495 | unsigned MSLocalManglingNumber) override { |
63 | 495 | return MSLocalManglingNumber; |
64 | 495 | } |
65 | | }; |
66 | | |
67 | | class MicrosoftCXXABI : public CXXABI { |
68 | | ASTContext &Context; |
69 | | llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; |
70 | | |
71 | | llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> |
72 | | UnnamedTagDeclToDeclaratorDecl; |
73 | | llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> |
74 | | UnnamedTagDeclToTypedefNameDecl; |
75 | | |
76 | | public: |
77 | 6.90k | MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } |
78 | | |
79 | | MemberPointerInfo |
80 | | getMemberPointerInfo(const MemberPointerType *MPT) const override; |
81 | | |
82 | 46.3k | CallingConv getDefaultMethodCallConv(bool isVariadic) const override { |
83 | 46.3k | if (!isVariadic && |
84 | 46.2k | Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) |
85 | 25.8k | return CC_X86ThisCall; |
86 | 20.4k | return Context.getTargetInfo().getDefaultCallingConv(); |
87 | 20.4k | } |
88 | | |
89 | 0 | bool isNearlyEmpty(const CXXRecordDecl *RD) const override { |
90 | 0 | llvm_unreachable("unapplicable to the MS ABI"); |
91 | 0 | } |
92 | | |
93 | | const CXXConstructorDecl * |
94 | 50 | getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { |
95 | 50 | return RecordToCopyCtor[RD]; |
96 | 50 | } |
97 | | |
98 | | void |
99 | | addCopyConstructorForExceptionObject(CXXRecordDecl *RD, |
100 | 20 | CXXConstructorDecl *CD) override { |
101 | 20 | assert(CD != nullptr); |
102 | 20 | assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); |
103 | 20 | RecordToCopyCtor[RD] = CD; |
104 | 20 | } |
105 | | |
106 | | void addTypedefNameForUnnamedTagDecl(TagDecl *TD, |
107 | 10 | TypedefNameDecl *DD) override { |
108 | 10 | TD = TD->getCanonicalDecl(); |
109 | 10 | DD = DD->getCanonicalDecl(); |
110 | 10 | TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; |
111 | 10 | if (!I) |
112 | 10 | I = DD; |
113 | 10 | } |
114 | | |
115 | 2.13k | TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { |
116 | 2.13k | return UnnamedTagDeclToTypedefNameDecl.lookup( |
117 | 2.13k | const_cast<TagDecl *>(TD->getCanonicalDecl())); |
118 | 2.13k | } |
119 | | |
120 | | void addDeclaratorForUnnamedTagDecl(TagDecl *TD, |
121 | 93 | DeclaratorDecl *DD) override { |
122 | 93 | TD = TD->getCanonicalDecl(); |
123 | 93 | DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); |
124 | 93 | DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; |
125 | 93 | if (!I) |
126 | 93 | I = DD; |
127 | 93 | } |
128 | | |
129 | 2.22k | DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { |
130 | 2.22k | return UnnamedTagDeclToDeclaratorDecl.lookup( |
131 | 2.22k | const_cast<TagDecl *>(TD->getCanonicalDecl())); |
132 | 2.22k | } |
133 | | |
134 | | std::unique_ptr<MangleNumberingContext> |
135 | 2.12k | createMangleNumberingContext() const override { |
136 | 2.12k | return std::make_unique<MicrosoftNumberingContext>(); |
137 | 2.12k | } |
138 | | }; |
139 | | } |
140 | | |
141 | | // getNumBases() seems to only give us the number of direct bases, and not the |
142 | | // total. This function tells us if we inherit from anybody that uses MI, or if |
143 | | // we have a non-primary base class, which uses the multiple inheritance model. |
144 | 527 | static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { |
145 | 621 | while (RD->getNumBases() > 0) { |
146 | 122 | if (RD->getNumBases() > 1) |
147 | 20 | return true; |
148 | 102 | assert(RD->getNumBases() == 1); |
149 | 102 | const CXXRecordDecl *Base = |
150 | 102 | RD->bases_begin()->getType()->getAsCXXRecordDecl(); |
151 | 102 | if (RD->isPolymorphic() && !Base->isPolymorphic()15 ) |
152 | 8 | return true; |
153 | 94 | RD = Base; |
154 | 94 | } |
155 | 499 | return false; |
156 | 527 | } |
157 | | |
158 | 628 | MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const { |
159 | 628 | if (!hasDefinition() || isParsingBaseSpecifiers()560 ) |
160 | 70 | return MSInheritanceModel::Unspecified; |
161 | 558 | if (getNumVBases() > 0) |
162 | 31 | return MSInheritanceModel::Virtual; |
163 | 527 | if (usesMultipleInheritanceModel(this)) |
164 | 28 | return MSInheritanceModel::Multiple; |
165 | 499 | return MSInheritanceModel::Single; |
166 | 499 | } |
167 | | |
168 | 2.69k | MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { |
169 | 2.69k | MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); |
170 | 2.69k | assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); |
171 | 2.69k | return IA->getInheritanceModel(); |
172 | 2.69k | } |
173 | | |
174 | 146 | bool CXXRecordDecl::nullFieldOffsetIsZero() const { |
175 | 146 | return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, |
176 | 146 | getMSInheritanceModel()) || |
177 | 102 | (hasDefinition() && isPolymorphic()100 ); |
178 | 146 | } |
179 | | |
180 | 1.68k | MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const { |
181 | 1.68k | if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) |
182 | 26 | return VDA->getVtorDispMode(); |
183 | 1.65k | return getASTContext().getLangOpts().getVtorDispMode(); |
184 | 1.65k | } |
185 | | |
186 | | // Returns the number of pointer and integer slots used to represent a member |
187 | | // pointer in the MS C++ ABI. |
188 | | // |
189 | | // Member function pointers have the following general form; however, fields |
190 | | // are dropped as permitted (under the MSVC interpretation) by the inheritance |
191 | | // model of the actual class. |
192 | | // |
193 | | // struct { |
194 | | // // A pointer to the member function to call. If the member function is |
195 | | // // virtual, this will be a thunk that forwards to the appropriate vftable |
196 | | // // slot. |
197 | | // void *FunctionPointerOrVirtualThunk; |
198 | | // |
199 | | // // An offset to add to the address of the vbtable pointer after |
200 | | // // (possibly) selecting the virtual base but before resolving and calling |
201 | | // // the function. |
202 | | // // Only needed if the class has any virtual bases or bases at a non-zero |
203 | | // // offset. |
204 | | // int NonVirtualBaseAdjustment; |
205 | | // |
206 | | // // The offset of the vb-table pointer within the object. Only needed for |
207 | | // // incomplete types. |
208 | | // int VBPtrOffset; |
209 | | // |
210 | | // // An offset within the vb-table that selects the virtual base containing |
211 | | // // the member. Loading from this offset produces a new offset that is |
212 | | // // added to the address of the vb-table pointer to produce the base. |
213 | | // int VirtualBaseAdjustmentOffset; |
214 | | // }; |
215 | | static std::pair<unsigned, unsigned> |
216 | 855 | getMSMemberPointerSlots(const MemberPointerType *MPT) { |
217 | 855 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
218 | 855 | MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); |
219 | 855 | unsigned Ptrs = 0; |
220 | 855 | unsigned Ints = 0; |
221 | 855 | if (MPT->isMemberFunctionPointer()) |
222 | 678 | Ptrs = 1; |
223 | 177 | else |
224 | 177 | Ints = 1; |
225 | 855 | if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(), |
226 | 855 | Inheritance)) |
227 | 140 | Ints++; |
228 | 855 | if (inheritanceModelHasVBPtrOffsetField(Inheritance)) |
229 | 159 | Ints++; |
230 | 855 | if (inheritanceModelHasVBTableOffsetField(Inheritance)) |
231 | 208 | Ints++; |
232 | 855 | return std::make_pair(Ptrs, Ints); |
233 | 855 | } |
234 | | |
235 | | CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( |
236 | 855 | const MemberPointerType *MPT) const { |
237 | | // The nominal struct is laid out with pointers followed by ints and aligned |
238 | | // to a pointer width if any are present and an int width otherwise. |
239 | 855 | const TargetInfo &Target = Context.getTargetInfo(); |
240 | 855 | unsigned PtrSize = Target.getPointerWidth(0); |
241 | 855 | unsigned IntSize = Target.getIntWidth(); |
242 | | |
243 | 855 | unsigned Ptrs, Ints; |
244 | 855 | std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); |
245 | 855 | MemberPointerInfo MPI; |
246 | 855 | MPI.HasPadding = false; |
247 | 855 | MPI.Width = Ptrs * PtrSize + Ints * IntSize; |
248 | | |
249 | | // When MSVC does x86_32 record layout, it aligns aggregate member pointers to |
250 | | // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for |
251 | | // function memptrs. |
252 | 855 | if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()230 ) |
253 | 102 | MPI.Align = 64; |
254 | 753 | else if (Ptrs) |
255 | 613 | MPI.Align = Target.getPointerAlign(0); |
256 | 140 | else |
257 | 140 | MPI.Align = Target.getIntAlign(); |
258 | | |
259 | 855 | if (Target.getTriple().isArch64Bit()) { |
260 | 361 | MPI.Width = llvm::alignTo(MPI.Width, MPI.Align); |
261 | 361 | MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize); |
262 | 361 | } |
263 | 855 | return MPI; |
264 | 855 | } |
265 | | |
266 | 6.90k | CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { |
267 | 6.90k | return new MicrosoftCXXABI(Ctx); |
268 | 6.90k | } |
269 | | |