/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/Mangle.h" |
20 | | #include "clang/AST/MangleNumberingContext.h" |
21 | | #include "clang/AST/RecordLayout.h" |
22 | | #include "clang/AST/Type.h" |
23 | | #include "clang/Basic/TargetInfo.h" |
24 | | |
25 | | using namespace clang; |
26 | | |
27 | | namespace { |
28 | | |
29 | | /// Numbers things which need to correspond across multiple TUs. |
30 | | /// Typically these are things like static locals, lambdas, or blocks. |
31 | | class MicrosoftNumberingContext : public MangleNumberingContext { |
32 | | llvm::DenseMap<const Type *, unsigned> ManglingNumbers; |
33 | | unsigned LambdaManglingNumber; |
34 | | unsigned StaticLocalNumber; |
35 | | unsigned StaticThreadlocalNumber; |
36 | | |
37 | | public: |
38 | | MicrosoftNumberingContext() |
39 | | : LambdaManglingNumber(0), StaticLocalNumber(0), |
40 | 2.20k | StaticThreadlocalNumber(0) {} |
41 | | |
42 | 1.67k | unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { |
43 | 1.67k | return ++LambdaManglingNumber; |
44 | 1.67k | } |
45 | | |
46 | 25 | unsigned getManglingNumber(const BlockDecl *BD) override { |
47 | 25 | const Type *Ty = nullptr; |
48 | 25 | return ++ManglingNumbers[Ty]; |
49 | 25 | } |
50 | | |
51 | 113 | unsigned getStaticLocalNumber(const VarDecl *VD) override { |
52 | 113 | if (VD->getTLSKind()) |
53 | 11 | return ++StaticThreadlocalNumber; |
54 | 102 | return ++StaticLocalNumber; |
55 | 113 | } |
56 | | |
57 | | unsigned getManglingNumber(const VarDecl *VD, |
58 | 113 | unsigned MSLocalManglingNumber) override { |
59 | 113 | return MSLocalManglingNumber; |
60 | 113 | } |
61 | | |
62 | | unsigned getManglingNumber(const TagDecl *TD, |
63 | 542 | unsigned MSLocalManglingNumber) override { |
64 | 542 | return MSLocalManglingNumber; |
65 | 542 | } |
66 | | }; |
67 | | |
68 | | class MSHIPNumberingContext : public MicrosoftNumberingContext { |
69 | | std::unique_ptr<MangleNumberingContext> DeviceCtx; |
70 | | |
71 | | public: |
72 | | using MicrosoftNumberingContext::getManglingNumber; |
73 | 7 | MSHIPNumberingContext(MangleContext *DeviceMangler) { |
74 | 7 | DeviceCtx = createItaniumNumberingContext(DeviceMangler); |
75 | 7 | } |
76 | | |
77 | 8 | unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { |
78 | 8 | return DeviceCtx->getManglingNumber(CallOperator); |
79 | 8 | } |
80 | | |
81 | | unsigned getManglingNumber(const TagDecl *TD, |
82 | 2 | unsigned MSLocalManglingNumber) override { |
83 | 2 | unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber); |
84 | 2 | unsigned HostN = |
85 | 2 | MicrosoftNumberingContext::getManglingNumber(TD, MSLocalManglingNumber); |
86 | 2 | if (DeviceN > 0xFFFF || HostN > 0xFFFF) { |
87 | 0 | DiagnosticsEngine &Diags = TD->getASTContext().getDiagnostics(); |
88 | 0 | unsigned DiagID = Diags.getCustomDiagID( |
89 | 0 | DiagnosticsEngine::Error, "Mangling number exceeds limit (65535)"); |
90 | 0 | Diags.Report(TD->getLocation(), DiagID); |
91 | 0 | } |
92 | 2 | return (DeviceN << 16) | HostN; |
93 | 2 | } |
94 | | }; |
95 | | |
96 | | class MSSYCLNumberingContext : public MicrosoftNumberingContext { |
97 | | std::unique_ptr<MangleNumberingContext> DeviceCtx; |
98 | | |
99 | | public: |
100 | 9 | MSSYCLNumberingContext(MangleContext *DeviceMangler) { |
101 | 9 | DeviceCtx = createItaniumNumberingContext(DeviceMangler); |
102 | 9 | } |
103 | | |
104 | 22 | unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { |
105 | 22 | return DeviceCtx->getManglingNumber(CallOperator); |
106 | 22 | } |
107 | | }; |
108 | | |
109 | | class MicrosoftCXXABI : public CXXABI { |
110 | | ASTContext &Context; |
111 | | llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; |
112 | | |
113 | | llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> |
114 | | UnnamedTagDeclToDeclaratorDecl; |
115 | | llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> |
116 | | UnnamedTagDeclToTypedefNameDecl; |
117 | | |
118 | | // MangleContext for device numbering context, which is based on Itanium C++ |
119 | | // ABI. |
120 | | std::unique_ptr<MangleContext> DeviceMangler; |
121 | | |
122 | | public: |
123 | 7.58k | MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { |
124 | 7.58k | if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()11 ) { |
125 | 9 | assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && |
126 | 9 | Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() && |
127 | 9 | "Unexpected combination of C++ ABIs."); |
128 | 9 | DeviceMangler.reset( |
129 | 9 | Context.createMangleContext(Context.getAuxTargetInfo())); |
130 | 9 | } |
131 | 7.57k | else if (Context.getLangOpts().isSYCL()) { |
132 | 2 | DeviceMangler.reset( |
133 | 2 | ItaniumMangleContext::create(Context, Context.getDiagnostics())); |
134 | 2 | } |
135 | 7.58k | } |
136 | | |
137 | | MemberPointerInfo |
138 | | getMemberPointerInfo(const MemberPointerType *MPT) const override; |
139 | | |
140 | 48.2k | CallingConv getDefaultMethodCallConv(bool isVariadic) const override { |
141 | 48.2k | if (!isVariadic && |
142 | 48.2k | Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x8648.1k ) |
143 | 26.2k | return CC_X86ThisCall; |
144 | 22.0k | return Context.getTargetInfo().getDefaultCallingConv(); |
145 | 48.2k | } |
146 | | |
147 | 0 | bool isNearlyEmpty(const CXXRecordDecl *RD) const override { |
148 | 0 | llvm_unreachable("unapplicable to the MS ABI"); |
149 | 0 | } |
150 | | |
151 | | const CXXConstructorDecl * |
152 | 31 | getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { |
153 | 31 | return RecordToCopyCtor[RD]; |
154 | 31 | } |
155 | | |
156 | | void |
157 | | addCopyConstructorForExceptionObject(CXXRecordDecl *RD, |
158 | 15 | CXXConstructorDecl *CD) override { |
159 | 15 | assert(CD != nullptr); |
160 | 15 | assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); |
161 | 15 | RecordToCopyCtor[RD] = CD; |
162 | 15 | } |
163 | | |
164 | | void addTypedefNameForUnnamedTagDecl(TagDecl *TD, |
165 | 10 | TypedefNameDecl *DD) override { |
166 | 10 | TD = TD->getCanonicalDecl(); |
167 | 10 | DD = DD->getCanonicalDecl(); |
168 | 10 | TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; |
169 | 10 | if (!I) |
170 | 10 | I = DD; |
171 | 10 | } |
172 | | |
173 | 2.26k | TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { |
174 | 2.26k | return UnnamedTagDeclToTypedefNameDecl.lookup( |
175 | 2.26k | const_cast<TagDecl *>(TD->getCanonicalDecl())); |
176 | 2.26k | } |
177 | | |
178 | | void addDeclaratorForUnnamedTagDecl(TagDecl *TD, |
179 | 95 | DeclaratorDecl *DD) override { |
180 | 95 | TD = TD->getCanonicalDecl(); |
181 | 95 | DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); |
182 | 95 | DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; |
183 | 95 | if (!I) |
184 | 95 | I = DD; |
185 | 95 | } |
186 | | |
187 | 2.35k | DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { |
188 | 2.35k | return UnnamedTagDeclToDeclaratorDecl.lookup( |
189 | 2.35k | const_cast<TagDecl *>(TD->getCanonicalDecl())); |
190 | 2.35k | } |
191 | | |
192 | | std::unique_ptr<MangleNumberingContext> |
193 | 2.20k | createMangleNumberingContext() const override { |
194 | 2.20k | if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()7 ) { |
195 | 7 | assert(DeviceMangler && "Missing device mangler"); |
196 | 7 | return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get()); |
197 | 2.20k | } else if (Context.getLangOpts().isSYCL()) { |
198 | 9 | assert(DeviceMangler && "Missing device mangler"); |
199 | 9 | return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get()); |
200 | 9 | } |
201 | | |
202 | 2.19k | return std::make_unique<MicrosoftNumberingContext>(); |
203 | 2.20k | } |
204 | | }; |
205 | | } |
206 | | |
207 | | // getNumBases() seems to only give us the number of direct bases, and not the |
208 | | // total. This function tells us if we inherit from anybody that uses MI, or if |
209 | | // we have a non-primary base class, which uses the multiple inheritance model. |
210 | 550 | static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { |
211 | 644 | while (RD->getNumBases() > 0) { |
212 | 124 | if (RD->getNumBases() > 1) |
213 | 22 | return true; |
214 | 102 | assert(RD->getNumBases() == 1); |
215 | 102 | const CXXRecordDecl *Base = |
216 | 102 | RD->bases_begin()->getType()->getAsCXXRecordDecl(); |
217 | 102 | if (RD->isPolymorphic() && !Base->isPolymorphic()15 ) |
218 | 8 | return true; |
219 | 94 | RD = Base; |
220 | 94 | } |
221 | 520 | return false; |
222 | 550 | } |
223 | | |
224 | 656 | MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const { |
225 | 656 | if (!hasDefinition() || isParsingBaseSpecifiers()586 ) |
226 | 72 | return MSInheritanceModel::Unspecified; |
227 | 584 | if (getNumVBases() > 0) |
228 | 34 | return MSInheritanceModel::Virtual; |
229 | 550 | if (usesMultipleInheritanceModel(this)) |
230 | 30 | return MSInheritanceModel::Multiple; |
231 | 520 | return MSInheritanceModel::Single; |
232 | 550 | } |
233 | | |
234 | 3.02k | MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { |
235 | 3.02k | MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); |
236 | 3.02k | assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); |
237 | 3.02k | return IA->getInheritanceModel(); |
238 | 3.02k | } |
239 | | |
240 | 146 | bool CXXRecordDecl::nullFieldOffsetIsZero() const { |
241 | 146 | return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, |
242 | 146 | getMSInheritanceModel()) || |
243 | 146 | (100 hasDefinition()100 && isPolymorphic()98 ); |
244 | 146 | } |
245 | | |
246 | 1.72k | MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const { |
247 | 1.72k | if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) |
248 | 26 | return VDA->getVtorDispMode(); |
249 | 1.69k | return getASTContext().getLangOpts().getVtorDispMode(); |
250 | 1.72k | } |
251 | | |
252 | | // Returns the number of pointer and integer slots used to represent a member |
253 | | // pointer in the MS C++ ABI. |
254 | | // |
255 | | // Member function pointers have the following general form; however, fields |
256 | | // are dropped as permitted (under the MSVC interpretation) by the inheritance |
257 | | // model of the actual class. |
258 | | // |
259 | | // struct { |
260 | | // // A pointer to the member function to call. If the member function is |
261 | | // // virtual, this will be a thunk that forwards to the appropriate vftable |
262 | | // // slot. |
263 | | // void *FunctionPointerOrVirtualThunk; |
264 | | // |
265 | | // // An offset to add to the address of the vbtable pointer after |
266 | | // // (possibly) selecting the virtual base but before resolving and calling |
267 | | // // the function. |
268 | | // // Only needed if the class has any virtual bases or bases at a non-zero |
269 | | // // offset. |
270 | | // int NonVirtualBaseAdjustment; |
271 | | // |
272 | | // // The offset of the vb-table pointer within the object. Only needed for |
273 | | // // incomplete types. |
274 | | // int VBPtrOffset; |
275 | | // |
276 | | // // An offset within the vb-table that selects the virtual base containing |
277 | | // // the member. Loading from this offset produces a new offset that is |
278 | | // // added to the address of the vb-table pointer to produce the base. |
279 | | // int VirtualBaseAdjustmentOffset; |
280 | | // }; |
281 | | static std::pair<unsigned, unsigned> |
282 | 865 | getMSMemberPointerSlots(const MemberPointerType *MPT) { |
283 | 865 | const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); |
284 | 865 | MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); |
285 | 865 | unsigned Ptrs = 0; |
286 | 865 | unsigned Ints = 0; |
287 | 865 | if (MPT->isMemberFunctionPointer()) |
288 | 686 | Ptrs = 1; |
289 | 179 | else |
290 | 179 | Ints = 1; |
291 | 865 | if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(), |
292 | 865 | Inheritance)) |
293 | 142 | Ints++; |
294 | 865 | if (inheritanceModelHasVBPtrOffsetField(Inheritance)) |
295 | 161 | Ints++; |
296 | 865 | if (inheritanceModelHasVBTableOffsetField(Inheritance)) |
297 | 211 | Ints++; |
298 | 865 | return std::make_pair(Ptrs, Ints); |
299 | 865 | } |
300 | | |
301 | | CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( |
302 | 865 | const MemberPointerType *MPT) const { |
303 | | // The nominal struct is laid out with pointers followed by ints and aligned |
304 | | // to a pointer width if any are present and an int width otherwise. |
305 | 865 | const TargetInfo &Target = Context.getTargetInfo(); |
306 | 865 | unsigned PtrSize = Target.getPointerWidth(LangAS::Default); |
307 | 865 | unsigned IntSize = Target.getIntWidth(); |
308 | | |
309 | 865 | unsigned Ptrs, Ints; |
310 | 865 | std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); |
311 | 865 | MemberPointerInfo MPI; |
312 | 865 | MPI.HasPadding = false; |
313 | 865 | MPI.Width = Ptrs * PtrSize + Ints * IntSize; |
314 | | |
315 | | // When MSVC does x86_32 record layout, it aligns aggregate member pointers to |
316 | | // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for |
317 | | // function memptrs. |
318 | 865 | if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()234 ) |
319 | 102 | MPI.Align = 64; |
320 | 763 | else if (Ptrs) |
321 | 621 | MPI.Align = Target.getPointerAlign(LangAS::Default); |
322 | 142 | else |
323 | 142 | MPI.Align = Target.getIntAlign(); |
324 | | |
325 | 865 | if (Target.getTriple().isArch64Bit()) { |
326 | 367 | MPI.Width = llvm::alignTo(MPI.Width, MPI.Align); |
327 | 367 | MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize); |
328 | 367 | } |
329 | 865 | return MPI; |
330 | 865 | } |
331 | | |
332 | 7.58k | CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { |
333 | 7.58k | return new MicrosoftCXXABI(Ctx); |
334 | 7.58k | } |